diff --git a/src/86box.c b/src/86box.c index ae58aca03..71f877599 100644 --- a/src/86box.c +++ b/src/86box.c @@ -188,7 +188,6 @@ int gfxcard[GFXCARD_MAX] = { 0, 0 }; /* (C) graphic int show_second_monitors = 1; /* (C) show non-primary monitors */ int sound_is_float = 1; /* (C) sound uses FP values */ int voodoo_enabled = 0; /* (C) video option */ -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 */ @@ -217,12 +216,15 @@ int test_mode = 0; /* (C) Test mo 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 force_10ms; /* (C) Force 10ms CPU frame intervals. */ int other_ide_present = 0; /* IDE controllers from non-IDE cards are present */ int other_scsi_present = 0; /* SCSI controllers from non-SCSI cards are present */ +int is_pcjr = 0; /* The current machine is PCjr. */ + // Accelerator key array struct accelKey acc_keys[NUM_ACCELS]; @@ -1532,9 +1534,6 @@ pc_reset_hard_init(void) if (unittester_enabled) device_add(&unittester_device); - if (lba_enhancer_enabled) - device_add(&lba_enhancer_device); - if (novell_keycard_enabled) device_add(&novell_keycard_device); @@ -1592,19 +1591,19 @@ update_mouse_msg(void) *(wcp - 1) = L'\0'; mbstowcs(wcpu, cpu_s->name, strlen(cpu_s->name) + 1); #ifdef _WIN32 - swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i%%%% - %ls", + swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i.%%i%%%% - %ls", plat_get_string(STRING_MOUSE_CAPTURE)); - swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%%i%%%% - %ls", + swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%%i.%%i%%%% - %ls", (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); - wcsncpy(mouse_msg[2], L"%i%%", sizeof_w(mouse_msg[2])); + wcsncpy(mouse_msg[2], L"%i.%i%%", sizeof_w(mouse_msg[2])); #else - swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", + swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%ls v%ls - %%i.%%i%%%% - %ls - %ls/%ls - %ls", EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu, plat_get_string(STRING_MOUSE_CAPTURE)); - swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", + swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%ls v%ls - %%i.%%i%%%% - %ls - %ls/%ls - %ls", EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu, (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB)); - swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls", + swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i.%%i%%%% - %ls - %ls/%ls", EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu); #endif } @@ -1714,7 +1713,7 @@ pc_run(void) /* Run a block of code. */ startblit(); - cpu_exec((int32_t) cpu_s->rspeed / 100); + cpu_exec((int32_t) cpu_s->rspeed / (force_10ms ? 100 : 1000)); ack_pause(); #ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ if (gdbstub_step == GDBSTUB_EXEC) { @@ -1729,14 +1728,14 @@ pc_run(void) /* Done with this frame, update statistics. */ framecount++; - if (++framecountx >= 100) { + if (++framecountx >= (force_10ms ? 100 : 1000)) { framecountx = 0; frames = 0; } if (title_update) { mouse_msg_idx = ((mouse_type == MOUSE_TYPE_NONE) || (mouse_input_mode >= 1)) ? 2 : !!mouse_capture; - swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps); + swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps / (force_10ms ? 1 : 10), force_10ms ? 0 : (fps % 10)); #ifdef __APPLE__ /* Needed due to modifying the UI on the non-main thread is a big no-no. */ dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title); diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index e0fa8b0b6..9f6966d24 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2655,7 +2655,7 @@ cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer) 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[ 6] = 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) */ diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 26a74016a..875dd72ca 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -746,8 +746,7 @@ codegen_skip: uop_MOV_PTR(ir, IREG_ea_seg, (void *) op_ea_seg); if (op_ssegs != last_op_ssegs) uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); - uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat); - uop_CALL_INSTRUCTION_FUNC(ir, op); + uop_CALL_INSTRUCTION_FUNC(ir, op, fetchdat); codegen_flags_changed = 0; codegen_mark_code_present(block, cs + cpu_state.pc, 8); diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 82cc79cfd..2bb6281ff 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -218,6 +218,7 @@ codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { + host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); host_arm64_call(block, uop->p); host_arm64_CBNZ(block, REG_X0, (uintptr_t) codegen_exit_rout); diff --git a/src/codegen_new/codegen_backend_arm_uops.c b/src/codegen_new/codegen_backend_arm_uops.c index b6963562c..b186e0e3b 100644 --- a/src/codegen_new/codegen_backend_arm_uops.c +++ b/src/codegen_new/codegen_backend_arm_uops.c @@ -286,6 +286,7 @@ codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { + host_arm_MOV_IMM(block, REG_ARG0, uop->imm_data); host_arm_call(block, uop->p); host_arm_TST_REG(block, REG_R0, REG_R0); host_arm_BNE(block, (uintptr_t) codegen_exit_rout); diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index 9ac8d2474..9f89012c6 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -68,8 +68,10 @@ jmp(codeblock_t *block, uintptr_t func) void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_ADD8_REG_IMM - dst_reg & 8\n"); +#endif if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -82,8 +84,10 @@ host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_ADD16_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -101,8 +105,10 @@ host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_ADD32_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -120,8 +126,10 @@ host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -132,8 +140,10 @@ host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_ADD8_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ @@ -141,8 +151,10 @@ host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_ADD16_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ @@ -150,8 +162,10 @@ host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_ADD32_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*ADD dst_reg, src_reg*/ @@ -160,8 +174,10 @@ host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_AND8_REG_IMM - dst_reg & 8\n"); +#endif if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -174,8 +190,10 @@ host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_AND16_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -193,8 +211,10 @@ host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_AND32_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -212,8 +232,10 @@ host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_AND8_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ @@ -221,8 +243,10 @@ host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_AND16_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ @@ -230,8 +254,10 @@ host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_AND32_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*AND dst_reg, src_reg*/ @@ -482,8 +508,10 @@ host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offs void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_LEA_REG_REG - bad reg\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/ @@ -492,8 +520,10 @@ host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8)) fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/ @@ -575,8 +605,10 @@ host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); +#ifdef RECOMPILER_DEBUG if (src_reg & 8) fatal("host_x86_MOV8_ABS_REG - bad reg\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); @@ -599,8 +631,10 @@ host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); +#ifdef RECOMPILER_DEBUG if (src_reg & 8) fatal("host_x86_MOV16_ABS_REG - bad reg\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); @@ -619,8 +653,10 @@ host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); +#ifdef RECOMPILER_DEBUG if (src_reg & 8) fatal("host_x86_MOV32_ABS_REG - bad reg\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); @@ -643,8 +679,10 @@ host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); +#ifdef RECOMPILER_DEBUG if (src_reg & 8) fatal("host_x86_MOV64_ABS_REG - bad reg\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); @@ -665,8 +703,11 @@ host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg) void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); +#endif + if (addr < 0x80 || addr >= 0xffffff80) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ @@ -680,24 +721,30 @@ host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_ void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/ } void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/ } void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/ } @@ -708,8 +755,10 @@ 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) + 2147483648ULL); +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_MOV8_REG_ABS reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); @@ -736,8 +785,10 @@ 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) + 2147483648ULL); +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_MOV16_REG_ABS reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); @@ -766,8 +817,10 @@ 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) + 2147483648ULL); +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_MOV32_REG_ABS reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 3); @@ -798,8 +851,10 @@ host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) { int64_t offset = (uintptr_t) p - (((uintptr_t) &cpu_state) + 128); +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_MOV64_REG_ABS reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); @@ -815,8 +870,10 @@ host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p) void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV8_REG_ABS_REG_REG_SHIFT reg & 8\n"); +#endif if (addr < 0x80 || addr >= 0xffffff80) { codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x8a, 0x44 | (dst_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/ @@ -830,8 +887,10 @@ host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t ad void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/ } @@ -839,8 +898,10 @@ host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (index_reg & 8)) fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n"); +#endif codegen_alloc_bytes(block, 4); if (base_reg & 8) codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/ @@ -851,8 +912,10 @@ host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_re void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV16_REG_BASE_OFFSET reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { @@ -869,8 +932,10 @@ host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV32_REG_BASE_OFFSET reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { @@ -886,8 +951,10 @@ host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV64_REG_BASE_OFFSET reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { @@ -905,8 +972,10 @@ host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, in void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((src_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV32_BASE_OFFSET_REG reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { @@ -922,8 +991,10 @@ host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((src_reg & 8) || (base_reg & 8)) fatal("host_x86_MOV64_BASE_OFFSET_REG reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { @@ -941,8 +1012,10 @@ host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (base_reg & 8) fatal("host_x86_MOV32_BASE_OFFSET_IMM reg & 8\n"); +#endif if (offset >= -128 && offset <= 127) { if (base_reg == REG_RSP) { @@ -961,16 +1034,21 @@ host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uin void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { +#ifdef RECOMPILER_DEBUG if (reg >= 8) fatal("host_x86_MOV8_REG_IMM reg >= 4\n"); +#endif + codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/ } void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) { +#ifdef RECOMPILER_DEBUG if (reg & 8) fatal("host_x86_MOV16_REG_IMM reg & 8\n"); +#endif codegen_alloc_bytes(block, 6); codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ codegen_addword(block, imm_data); @@ -978,8 +1056,10 @@ host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data) void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (reg & 8) fatal("host_x86_MOV32_REG_IMM reg & 8\n"); +#endif codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/ codegen_addlong(block, imm_data); @@ -1002,8 +1082,10 @@ host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data) void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV8_REG_REG - bad reg\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); @@ -1011,8 +1093,10 @@ host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV16_REG_REG - bad reg\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); @@ -1020,8 +1104,10 @@ host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOV32_REG_REG - bad reg\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); @@ -1068,8 +1154,10 @@ host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); @@ -1077,8 +1165,10 @@ host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, in void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8)) fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); @@ -1087,8 +1177,10 @@ host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, i void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ @@ -1096,8 +1188,10 @@ host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg) void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_32_8 - bad reg\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ @@ -1105,8 +1199,10 @@ host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg) void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_MOVZX_REG_16_8 - bad reg\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/ @@ -1118,8 +1214,10 @@ 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) + 2147483648ULL); +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 5); @@ -1145,7 +1243,7 @@ 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) + 2147483648ULL); -#if 0 +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n"); #endif @@ -1184,8 +1282,10 @@ 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) + 2147483648ULL); +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n"); +#endif if (offset >= -128 && offset <= 127) { codegen_alloc_bytes(block, 4); @@ -1214,8 +1314,10 @@ host_x86_NOP(codeblock_t *block) void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); +#endif if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -1228,8 +1330,10 @@ host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -1247,8 +1351,10 @@ host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -1266,8 +1372,10 @@ host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_OR8_REG_IMM - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ @@ -1275,8 +1383,10 @@ host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_OR16_REG_IMM - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ @@ -1284,8 +1394,10 @@ host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_OR32_REG_IMM - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*OR dst_reg, src_reg*/ @@ -1325,24 +1437,30 @@ host_x86_RET(codeblock_t *block) void host_x86_ROL8_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROL8 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_ROL16_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROL16 CL & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ } void host_x86_ROL32_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROL32 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROL | dst_reg); /*SHL dst_reg, CL*/ } @@ -1350,24 +1468,30 @@ host_x86_ROL32_CL(codeblock_t *block, int dst_reg) void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROL8 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROL16 imm & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ } void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROL32 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROL | dst_reg, shift); /*SHL dst_reg, shift*/ } @@ -1375,24 +1499,30 @@ host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_ROR8_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROR8 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_ROR16_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROR16 CL & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ } void host_x86_ROR32_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROR32 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_ROR | dst_reg); /*SHR dst_reg, CL*/ } @@ -1400,24 +1530,30 @@ host_x86_ROR32_CL(codeblock_t *block, int dst_reg) void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROR8 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROR16 imm & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ } void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("ROR32 im & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_ROR | dst_reg, shift); /*SHR dst_reg, shift*/ } @@ -1425,8 +1561,10 @@ host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SAR8_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SAR8 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ @@ -1434,8 +1572,10 @@ host_x86_SAR8_CL(codeblock_t *block, int dst_reg) void host_x86_SAR16_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SAR16 CL & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ @@ -1443,8 +1583,10 @@ host_x86_SAR16_CL(codeblock_t *block, int dst_reg) void host_x86_SAR32_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SAR32 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SAR | dst_reg); /*SAR dst_reg, CL*/ @@ -1453,8 +1595,10 @@ host_x86_SAR32_CL(codeblock_t *block, int dst_reg) void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SAR8 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ @@ -1462,8 +1606,10 @@ host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SAR16 imm & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ @@ -1471,8 +1617,10 @@ host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SAR32 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SAR | dst_reg, shift); /*SAR dst_reg, shift*/ } @@ -1480,8 +1628,10 @@ host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SHL8_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHL8 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ @@ -1489,8 +1639,10 @@ host_x86_SHL8_CL(codeblock_t *block, int dst_reg) void host_x86_SHL16_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHL16 CL & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ @@ -1498,8 +1650,10 @@ host_x86_SHL16_CL(codeblock_t *block, int dst_reg) void host_x86_SHL32_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHL32 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHL | dst_reg); /*SHL dst_reg, CL*/ @@ -1508,8 +1662,10 @@ host_x86_SHL32_CL(codeblock_t *block, int dst_reg) void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHL8 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ @@ -1517,8 +1673,10 @@ host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHL16 imm & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ @@ -1526,8 +1684,10 @@ host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHL32 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHL | dst_reg, shift); /*SHL dst_reg, shift*/ @@ -1536,8 +1696,10 @@ host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SHR8_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHR8 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd2, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ @@ -1545,8 +1707,10 @@ host_x86_SHR8_CL(codeblock_t *block, int dst_reg) void host_x86_SHR16_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHR16 CL & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ @@ -1554,8 +1718,10 @@ host_x86_SHR16_CL(codeblock_t *block, int dst_reg) void host_x86_SHR32_CL(codeblock_t *block, int dst_reg) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHR32 CL & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0xd3, 0xc0 | RM_OP_SHR | dst_reg); /*SHR dst_reg, CL*/ @@ -1564,8 +1730,10 @@ host_x86_SHR32_CL(codeblock_t *block, int dst_reg) void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHR8 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc0, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ @@ -1573,8 +1741,10 @@ host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHR16 imm & 8\n"); +#endif codegen_alloc_bytes(block, 4); codegen_addbyte4(block, 0x66, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ @@ -1582,8 +1752,10 @@ host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("SHR32 imm & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/ } @@ -1591,8 +1763,10 @@ host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift) void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_SUB8_REG_IMM - dst_reg & 8\n"); +#endif if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -1605,8 +1779,10 @@ host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_SUB16_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -1624,8 +1800,10 @@ host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_SUB32_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -1643,8 +1821,10 @@ host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -1655,8 +1835,10 @@ host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data) void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_SUB8_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ @@ -1664,8 +1846,10 @@ host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_SUB16_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ @@ -1673,8 +1857,10 @@ host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_SUB32_REG_REG - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*SUB dst_reg, src_reg*/ @@ -1697,8 +1883,10 @@ host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg) void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_TEST32_REG - bad reg\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/ @@ -1706,8 +1894,10 @@ host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg) void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("TEST32_REG_IMM reg & 8\n"); +#endif if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 5); codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/ @@ -1722,8 +1912,10 @@ host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); +#endif if (dst_reg == REG_EAX) { codegen_alloc_bytes(block, 2); @@ -1736,8 +1928,10 @@ host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data) void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 4); @@ -1755,8 +1949,10 @@ host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data) void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) { +#ifdef RECOMPILER_DEBUG if (dst_reg & 8) fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); +#endif if (is_imm8(imm_data)) { codegen_alloc_bytes(block, 3); @@ -1774,8 +1970,10 @@ host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data) void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_XOR8_REG_IMM - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ @@ -1783,8 +1981,10 @@ host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_XOR16_REG_IMM - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 3); codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ @@ -1792,8 +1992,10 @@ host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg) void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg) { +#ifdef RECOMPILER_DEBUG if ((dst_reg & 8) || (src_reg & 8)) fatal("host_x86_XOR32_REG_IMM - dst_reg & 8\n"); +#endif codegen_alloc_bytes(block, 2); codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); /*XOR dst_reg, src_reg*/ diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index 655896b54..6b68434a0 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -219,6 +219,11 @@ codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { +# if _WIN64 + host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); +# else + host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); +# endif host_x86_CALL(block, uop->p); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); host_x86_JNZ(block, codegen_exit_rout); diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c index 02c441234..fad088822 100644 --- a/src/codegen_new/codegen_backend_x86_uops.c +++ b/src/codegen_new/codegen_backend_x86_uops.c @@ -221,6 +221,7 @@ codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop) static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { + host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data); host_x86_CALL(block, uop->p); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); host_x86_JNZ(block, codegen_exit_rout); diff --git a/src/codegen_new/codegen_ir.c b/src/codegen_new/codegen_ir.c index ed8ae051f..d14fa0f23 100644 --- a/src/codegen_new/codegen_ir.c +++ b/src/codegen_new/codegen_ir.c @@ -38,7 +38,7 @@ codegen_ir_set_unroll(int count, int start, int first_instruction) static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) { - uop_t *new_uop = uop_alloc(ir, uop->type); + uop_t *new_uop = uop_alloc_unroll(ir, uop->type); if (!ir_reg_is_invalid(uop->src_reg_a)) new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg); diff --git a/src/codegen_new/codegen_ir_defs.h b/src/codegen_new/codegen_ir_defs.h index d55e57f3d..60f7badea 100644 --- a/src/codegen_new/codegen_ir_defs.h +++ b/src/codegen_new/codegen_ir_defs.h @@ -41,8 +41,8 @@ #define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER) #define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER) #define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER) -/*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/ -#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER) +/*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p with fetchdat, check return value and exit block if non-zero*/ +#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | UOP_TYPE_PARAMS_IMM | 0x11 | UOP_TYPE_BARRIER) #define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12) #define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13) /*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/ @@ -377,6 +377,34 @@ uop_alloc(ir_data_t *ir, uint32_t uop_type) uop->jump_dest_uop = -1; uop->jump_list_next = -1; + if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) + dirty_ir_regs[0] = dirty_ir_regs[1] = ~0ULL; + + return uop; +} + +static inline uop_t * +uop_alloc_unroll(ir_data_t *ir, uint32_t uop_type) +{ + uop_t *uop; + + if (ir->wr_pos >= UOP_NR_MAX) + fatal("Exceeded uOP max\n"); + + 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; + uop->src_reg_c = invalid_ir_reg; + + uop->pc = cpu_state.oldpc; + + uop->jump_dest_uop = -1; + uop->jump_list_next = -1; + if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)) codegen_reg_mark_as_required(); @@ -662,7 +690,7 @@ uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int sr #define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p) #define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p) -#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p) +#define uop_CALL_INSTRUCTION_FUNC(ir, p, imm) uop_gen_pointer_imm(UOP_CALL_INSTRUCTION_FUNC, ir, p, imm) #define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm) diff --git a/src/codegen_new/codegen_reg.c b/src/codegen_new/codegen_reg.c index 75cf25ded..f91377df8 100644 --- a/src/codegen_new/codegen_reg.c +++ b/src/codegen_new/codegen_reg.c @@ -34,6 +34,8 @@ typedef struct host_reg_set_t { static host_reg_set_t host_reg_set; static host_reg_set_t host_fp_reg_set; +uint64_t dirty_ir_regs[2] = { 0, 0 }; + enum { REG_BYTE, REG_WORD, @@ -184,15 +186,36 @@ struct [IREG_temp1d] = { REG_DOUBLE, (void *) 48, REG_FP, REG_VOLATILE }, }; +static const uint8_t native_requested_sizes[9][8] = +{ + [REG_BYTE][IREG_SIZE_B >> IREG_SIZE_SHIFT] = 1, + [REG_FPU_ST_BYTE][IREG_SIZE_B >> IREG_SIZE_SHIFT] = 1, + [REG_WORD][IREG_SIZE_W >> IREG_SIZE_SHIFT] = 1, + [REG_DWORD][IREG_SIZE_L >> IREG_SIZE_SHIFT] = 1, + [REG_QWORD][IREG_SIZE_D >> IREG_SIZE_SHIFT] = 1, + [REG_FPU_ST_QWORD][IREG_SIZE_D >> IREG_SIZE_SHIFT] = 1, + [REG_DOUBLE][IREG_SIZE_D >> IREG_SIZE_SHIFT] = 1, + [REG_FPU_ST_DOUBLE][IREG_SIZE_D >> IREG_SIZE_SHIFT] = 1, + [REG_QWORD][IREG_SIZE_Q >> IREG_SIZE_SHIFT] = 1, + [REG_FPU_ST_QWORD][IREG_SIZE_Q >> IREG_SIZE_SHIFT] = 1, + [REG_DOUBLE][IREG_SIZE_Q >> IREG_SIZE_SHIFT] = 1, + [REG_FPU_ST_DOUBLE][IREG_SIZE_Q >> IREG_SIZE_SHIFT] = 1, + + [REG_POINTER][(sizeof(void *) == 4) ? (IREG_SIZE_L >> IREG_SIZE_SHIFT) : (IREG_SIZE_Q >> IREG_SIZE_SHIFT)] = 1 +}; + void codegen_reg_mark_as_required(void) { - for (uint8_t reg = 0; reg < IREG_COUNT; reg++) { + /* This used to start from IREG_EAX, now only starts from IREG_ESP since the first 4 registers are never optimized out. */ + /* It also no longer iterates through volatile registers unnecessarily. */ + for (uint8_t reg = IREG_ESP; reg < IREG_temp0; reg++) { int last_version = reg_last_version[reg]; - if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT) + if (last_version > 0) reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED; } + dirty_ir_regs[0] = dirty_ir_regs[1] = 0; } int @@ -201,29 +224,7 @@ reg_is_native_size(ir_reg_t ir_reg) int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size; int requested_size = IREG_GET_SIZE(ir_reg.reg); - switch (native_size) { - case REG_BYTE: - case REG_FPU_ST_BYTE: - return (requested_size == IREG_SIZE_B); - case REG_WORD: - return (requested_size == IREG_SIZE_W); - case REG_DWORD: - return (requested_size == IREG_SIZE_L); - case REG_QWORD: - case REG_FPU_ST_QWORD: - case REG_DOUBLE: - case REG_FPU_ST_DOUBLE: - return ((requested_size == IREG_SIZE_D) || (requested_size == IREG_SIZE_Q)); - case REG_POINTER: - if (sizeof(void *) == 4) - return (requested_size == IREG_SIZE_L); - return (requested_size == IREG_SIZE_Q); - - default: - fatal("get_reg_is_native_size: unknown native size %i\n", native_size); - } - - return 0; + return native_requested_sizes[native_size][requested_size >> IREG_SIZE_SHIFT]; } void @@ -256,6 +257,8 @@ codegen_reg_reset(void) host_fp_reg_set.locked = 0; host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS; + dirty_ir_regs[0] = dirty_ir_regs[1] = 0; + for (c = 0; c < IREG_COUNT; c++) { reg_last_version[c] = 0; reg_version[c][0].refcount = 0; diff --git a/src/codegen_new/codegen_reg.h b/src/codegen_new/codegen_reg.h index 2185fde45..a86bcd1cf 100644 --- a/src/codegen_new/codegen_reg.h +++ b/src/codegen_new/codegen_reg.h @@ -16,59 +16,45 @@ #define IREG_SIZE_Q (5 << IREG_SIZE_SHIFT) enum { - IREG_EAX = 0, - IREG_ECX = 1, - IREG_EDX = 2, - IREG_EBX = 3, - IREG_ESP = 4, - IREG_EBP = 5, - IREG_ESI = 6, - IREG_EDI = 7, + IREG_EAX, + IREG_ECX, + IREG_EDX, + IREG_EBX, + IREG_ESP, + IREG_EBP, + IREG_ESI, + IREG_EDI, - IREG_flags_op = 8, - IREG_flags_res = 9, - IREG_flags_op1 = 10, - IREG_flags_op2 = 11, + IREG_flags_op, + IREG_flags_res, + IREG_flags_op1, + IREG_flags_op2, - IREG_pc = 12, - IREG_oldpc = 13, + IREG_pc, + IREG_oldpc, - IREG_eaaddr = 14, - IREG_ea_seg = 15, - IREG_op32 = 16, - IREG_ssegsx = 17, + IREG_eaaddr, + IREG_ea_seg, + IREG_op32, + IREG_ssegsx, - IREG_rm_mod_reg = 18, + IREG_rm_mod_reg, - IREG_acycs = 19, - IREG_cycles = 20, + IREG_cycles, - IREG_CS_base = 21, - IREG_DS_base = 22, - IREG_ES_base = 23, - IREG_FS_base = 24, - IREG_GS_base = 25, - IREG_SS_base = 26, + IREG_CS_base, + IREG_DS_base, + IREG_ES_base, + IREG_FS_base, + IREG_GS_base, + IREG_SS_base, - IREG_CS_seg = 27, - IREG_DS_seg = 28, - IREG_ES_seg = 29, - IREG_FS_seg = 30, - IREG_GS_seg = 31, - IREG_SS_seg = 32, - - /*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.*/ - IREG_temp0 = 33, - IREG_temp1 = 34, - IREG_temp2 = 35, - IREG_temp3 = 36, - - IREG_FPU_TOP = 37, - - IREG_temp0d = 38, - IREG_temp1d = 39, + IREG_CS_seg, + IREG_DS_seg, + IREG_ES_seg, + IREG_FS_seg, + IREG_GS_seg, + IREG_SS_seg, /*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag() to access. @@ -76,66 +62,79 @@ enum { used directly to index the stack. When it is clear, the difference between the current value of TOP and the value when the block was first compiled will be added to adjust for any changes in TOP.*/ - IREG_ST0 = 40, - IREG_ST1 = 41, - IREG_ST2 = 42, - IREG_ST3 = 43, - IREG_ST4 = 44, - IREG_ST5 = 45, - IREG_ST6 = 46, - IREG_ST7 = 47, + IREG_ST0, + IREG_ST1, + IREG_ST2, + IREG_ST3, + IREG_ST4, + IREG_ST5, + IREG_ST6, + IREG_ST7, - IREG_tag0 = 48, - IREG_tag1 = 49, - IREG_tag2 = 50, - IREG_tag3 = 51, - IREG_tag4 = 52, - IREG_tag5 = 53, - IREG_tag6 = 54, - IREG_tag7 = 55, + IREG_tag0, + IREG_tag1, + IREG_tag2, + IREG_tag3, + IREG_tag4, + IREG_tag5, + IREG_tag6, + IREG_tag7, - IREG_ST0_i64 = 56, - IREG_ST1_i64 = 57, - IREG_ST2_i64 = 58, - IREG_ST3_i64 = 59, - IREG_ST4_i64 = 60, - IREG_ST5_i64 = 61, - IREG_ST6_i64 = 62, - IREG_ST7_i64 = 63, + IREG_ST0_i64, + IREG_ST1_i64, + IREG_ST2_i64, + IREG_ST3_i64, + IREG_ST4_i64, + IREG_ST5_i64, + IREG_ST6_i64, + IREG_ST7_i64, - IREG_MM0x = 64, - IREG_MM1x = 65, - IREG_MM2x = 66, - IREG_MM3x = 67, - IREG_MM4x = 68, - IREG_MM5x = 69, - IREG_MM6x = 70, - IREG_MM7x = 71, + IREG_MM0x, + IREG_MM1x, + IREG_MM2x, + IREG_MM3x, + IREG_MM4x, + IREG_MM5x, + IREG_MM6x, + IREG_MM7x, - IREG_NPXCx = 72, - IREG_NPXSx = 73, + IREG_NPXCx, + IREG_NPXSx, - IREG_flagsx = 74, - IREG_eflagsx = 75, + IREG_flagsx, + IREG_eflagsx, - IREG_CS_limit_low = 76, - IREG_DS_limit_low = 77, - IREG_ES_limit_low = 78, - IREG_FS_limit_low = 79, - IREG_GS_limit_low = 80, - IREG_SS_limit_low = 81, + IREG_CS_limit_low, + IREG_DS_limit_low, + IREG_ES_limit_low, + IREG_FS_limit_low, + IREG_GS_limit_low, + IREG_SS_limit_low, - IREG_CS_limit_high = 82, - IREG_DS_limit_high = 83, - IREG_ES_limit_high = 84, - IREG_FS_limit_high = 85, - IREG_GS_limit_high = 86, - IREG_SS_limit_high = 87, + IREG_CS_limit_high, + IREG_DS_limit_high, + IREG_ES_limit_high, + IREG_FS_limit_high, + IREG_GS_limit_high, + IREG_SS_limit_high, - IREG_eaa16 = 88, - IREG_x87_op = 89, + IREG_eaa16, + IREG_x87_op, - IREG_COUNT = 90, + IREG_FPU_TOP, + + /*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.*/ + IREG_temp0, + IREG_temp1, + IREG_temp2, + IREG_temp3, + + IREG_temp0d, + IREG_temp1d, + + IREG_COUNT, IREG_INVALID = 255, @@ -279,6 +278,7 @@ ireg_seg_limit_high(x86seg *seg) } extern uint8_t reg_last_version[IREG_COUNT]; +extern uint64_t dirty_ir_regs[2]; /*This version of the register must be calculated, regardless of whether it is apparently required or not. Do not optimise out.*/ @@ -363,10 +363,12 @@ codegen_reg_write(int reg, int uop_nr) int last_version = reg_last_version[IREG_GET_REG(reg)]; reg_version_t *version; -#ifndef RELEASE_BUILD - if (IREG_GET_REG(reg) == IREG_INVALID) - fatal("codegen_reg_write - IREG_INVALID\n"); -#endif + if (dirty_ir_regs[(IREG_GET_REG(reg) >> 6) & 3] & (1ull << ((uint64_t)IREG_GET_REG(reg) & 0x3full))) { + dirty_ir_regs[(IREG_GET_REG(reg) >> 6) & 3] &= ~(1ull << ((uint64_t)IREG_GET_REG(reg) & 0x3full)); + if ((IREG_GET_REG(reg) > IREG_EBX && IREG_GET_REG(reg) < IREG_temp0) && last_version > 0) { + reg_version[IREG_GET_REG(reg)][last_version].flags |= REG_FLAGS_REQUIRED; + } + } ireg.reg = reg; ireg.version = last_version + 1; @@ -376,12 +378,8 @@ codegen_reg_write(int reg, int uop_nr) } reg_last_version[IREG_GET_REG(reg)]++; -#ifndef RELEASE_BUILD - if (!reg_last_version[IREG_GET_REG(reg)]) - fatal("codegen_reg_write - version overflow\n"); - else -#endif - if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX) + + if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX) CPU_BLOCK_END(); if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount) max_version_refcount = reg_last_version[IREG_GET_REG(reg)]; diff --git a/src/config.c b/src/config.c index d33813e7d..acfbec758 100644 --- a/src/config.c +++ b/src/config.c @@ -144,6 +144,8 @@ load_general(void) video_grayscale = ini_section_get_int(cat, "video_grayscale", 0); video_graytype = ini_section_get_int(cat, "video_graytype", 0); + force_10ms = !!ini_section_get_int(cat, "force_10ms", 0); + rctrl_is_lalt = ini_section_get_int(cat, "rctrl_is_lalt", 0); update_icons = ini_section_get_int(cat, "update_icons", 1); @@ -263,7 +265,9 @@ load_machine(void) if (p != NULL) { migrate_from = p; /* Migrate renamed machines. */ - if (!strcmp(p, "430nx")) + if (!strcmp(p, "tandy")) + machine = machine_get_machine_from_internal_name("tandy1000sx"); + else if (!strcmp(p, "430nx")) machine = machine_get_machine_from_internal_name("586ip"); else if (!strcmp(p, "586mc1")) machine = machine_get_machine_from_internal_name("586is"); @@ -658,9 +662,9 @@ load_network(void) nc->net_type = NET_TYPE_PCAP; else if (!strcmp(p, "slirp") || !strcmp(p, "2")) nc->net_type = NET_TYPE_SLIRP; - else if (!strcmp(p, "vde") || !strcmp(p, "2")) + else if (!strcmp(p, "vde") || !strcmp(p, "3")) nc->net_type = NET_TYPE_VDE; - else if (!strcmp(p, "tap") || !strcmp(p, "3")) + else if (!strcmp(p, "tap") || !strcmp(p, "4")) nc->net_type = NET_TYPE_TAP; else nc->net_type = NET_TYPE_NONE; @@ -706,9 +710,9 @@ load_network(void) nc->net_type = NET_TYPE_PCAP; else if (!strcmp(p, "slirp") || !strcmp(p, "2")) nc->net_type = NET_TYPE_SLIRP; - else if (!strcmp(p, "vde") || !strcmp(p, "2")) + else if (!strcmp(p, "vde") || !strcmp(p, "3")) nc->net_type = NET_TYPE_VDE; - else if (!strcmp(p, "tap") || !strcmp(p, "3")) + else if (!strcmp(p, "tap") || !strcmp(p, "4")) nc->net_type = NET_TYPE_TAP; else nc->net_type = NET_TYPE_NONE; @@ -990,11 +994,6 @@ load_storage_controllers(void) } } } - - lba_enhancer_enabled = !!ini_section_get_int(cat, "lba_enhancer_enabled", 0); - - if (!lba_enhancer_enabled) - ini_section_delete_var(cat, "lba_enhancer_enabled"); } /* Load "Hard Disks" section. */ @@ -1211,14 +1210,20 @@ load_floppy_and_cdrom_drives(void) unsigned int board = 0; unsigned int dev = 0; int c; - int d = 0; + int d; int count = cdrom_get_type_count(); memset(temp, 0x00, sizeof(temp)); for (c = 0; c < FDD_NUM; c++) { sprintf(temp, "fdd_%02i_type", c + 1); p = ini_section_get_string(cat, temp, (c < 2) ? "525_2dd" : "none"); - fdd_set_type(c, fdd_get_from_internal_name(p)); + if (!strcmp(p, "525_2hd_ps2")) + d = fdd_get_from_internal_name("525_2hd"); + else if (!strcmp(p, "35_2hd_ps2")) + d = fdd_get_from_internal_name("35_2hd"); + else + d = fdd_get_from_internal_name(p); + fdd_set_type(c, d); if (fdd_get_type(c) > 13) fdd_set_type(c, 13); @@ -1297,6 +1302,7 @@ load_floppy_and_cdrom_drives(void) ini_section_delete_var(cat, temp); sprintf(temp, "cdrom_%02i_parameters", c + 1); + d = 0; p = ini_section_get_string(cat, temp, NULL); if (p != NULL) sscanf(p, "%01u, %s", &d, s); @@ -1725,6 +1731,17 @@ load_other_peripherals(void) ini_section_delete_var(cat, temp); } + /* Backwards compatibility for standalone LBA Enhancer from v4.2 and older. */ + if (ini_section_get_int(ini_find_section(config, "Storage controllers"), "lba_enhancer_enabled", 0) == 1) { + /* Migrate to the first available ISA ROM slot. */ + for (uint8_t c = 0; c < ISAROM_MAX; c++) { + if (!isarom_type[c]) { + isarom_type[c] = isarom_get_from_internal_name("lba_enhancer"); + break; + } + } + } + p = ini_section_get_string(cat, "isartc_type", "none"); isartc_type = isartc_get_from_internal_name(p); @@ -1947,6 +1964,10 @@ save_general(void) const char *va_name; + ini_section_set_int(cat, "force_10ms", force_10ms); + if (force_10ms == 0) + ini_section_delete_var(cat, "force_10ms"); + ini_section_set_int(cat, "inhibit_multimedia_keys", inhibit_multimedia_keys); if (inhibit_multimedia_keys == 0) ini_section_delete_var(cat, "inhibit_multimedia_keys"); @@ -2691,10 +2712,19 @@ save_storage_controllers(void) } } - if (lba_enhancer_enabled == 0) + /* Downgrade compatibility for standalone LBA Enhancer from v4.2 and older. */ + int card_id = isarom_get_from_internal_name("lba_enhancer"); + for (c = 0; c < ISAROM_MAX; c++) { + if (isarom_type[c] == card_id) { + /* A special value of 2 still enables the cards on older versions, + but lets newer versions know that they've already been migrated. */ + ini_section_set_int(cat, "lba_enhancer_enabled", 2); + card_id = 0; /* mark as found */ + break; + } + } + if (card_id > 0) /* not found */ ini_section_delete_var(cat, "lba_enhancer_enabled"); - else - ini_section_set_int(cat, "lba_enhancer_enabled", 1); ini_delete_section_if_empty(config, cat); } diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index fd6285057..23f3f1e35 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -739,7 +739,7 @@ exec386_dynarec(int32_t cycs) uint64_t oldtsc; uint64_t delta; - int32_t cyc_period = cycs / 2000; /*5us*/ + int32_t cyc_period = cycs / (force_10ms ? 2000 : 200); /*5us*/ # ifdef USE_ACYCS acycs = 0; diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 2e24d3c49..edab16567 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1226,22 +1226,24 @@ custom_nmi(void) } static int -irq_pending(void) +irq_pending(int nec_hlt) { uint8_t temp; + int i_flag = (cpu_state.flags & I_FLAG) || nec_hlt; - temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint); + temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || (i_flag && pic.int_pending && !noint); return temp; } static void -check_interrupts(void) +check_interrupts(int nec_hlt) { int temp; + int i_flag = (cpu_state.flags & I_FLAG) || nec_hlt; - if (irq_pending()) { - if ((cpu_state.flags & T_FLAG) && !noint) { + if (irq_pending(nec_hlt)) { + if ((cpu_state.flags & T_FLAG) && !(noint & 1)) { interrupt(1); return; } @@ -1256,7 +1258,7 @@ check_interrupts(void) #endif return; } - if ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint) { + if (i_flag && pic.int_pending && !noint) { repeating = 0; completed = 1; ovr_seg = NULL; @@ -1289,7 +1291,7 @@ rep_action(int bits) return 0; wait_cycs(2, 0); t = CX; - if (irq_pending() && (repeating != 0)) { + if (irq_pending(0) && (repeating != 0)) { access(71, bits); pfq_clear(); if (is_nec && (ovr_seg != NULL)) @@ -3008,9 +3010,9 @@ execx86(int cycs) wait_cycs(2, 0); wait_cycs(5, 0); #ifdef NO_HACK - if (irq_pending()) { + if (irq_pending(0)) { wait_cycs(7, 0); - check_interrupts(); + check_interrupts(0); } else { repeating = 1; completed = 0; @@ -3018,7 +3020,7 @@ execx86(int cycs) } #else wait_cycs(7, 0); - check_interrupts(); + check_interrupts(0); #endif break; case 0x9C: /*PUSHF*/ @@ -3029,16 +3031,19 @@ execx86(int cycs) tempw = (cpu_state.flags & 0x0fd7) | 0xf000; push(&tempw); break; - case 0x9D: /*POPF*/ + case 0x9D: { /*POPF*/ + uint16_t old_flags = cpu_state.flags; access(25, 16); if (is_nec && cpu_md_write_disable) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; wait_cycs(1, 0); + if ((old_flags ^ cpu_state.flags) & T_FLAG) + noint = 1; sync_to_i8080(); break; - case 0x9E: /*SAHF*/ + } case 0x9E: /*SAHF*/ wait_cycs(1, 0); cpu_state.flags = (cpu_state.flags & 0xff02) | AH; wait_cycs(2, 0); @@ -3307,7 +3312,7 @@ execx86(int cycs) else cpu_state.flags = pop() | 0x0002; wait_cycs(5, 0); - noint = 1; + noint = 2; nmi_enable = 1; if (is_nec && !(cpu_state.flags & MD_FLAG)) sync_to_i8080(); @@ -3647,9 +3652,9 @@ execx86(int cycs) pfq_clear(); } wait_cycs(1, 0); - if (irq_pending()) { + if (irq_pending(is_nec)) { wait_cycs(cycles & 1, 0); - check_interrupts(); + check_interrupts(is_nec); } else { repeating = 1; completed = 0; @@ -3848,7 +3853,7 @@ exec_completed: if (in_lock) clear_lock = 1; clock_end(); - check_interrupts(); + check_interrupts(0); if (noint) noint = 0; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 8524306dc..db8c89ebb 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -688,6 +688,23 @@ const cpu_family_t cpu_families[] = { .cache_write_cycles = 0, .atclk_div = 1 }, + { + .name = "8", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 8000000, + .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_V20, @@ -911,10 +928,10 @@ const cpu_family_t cpu_families[] = { .internal_name = "necv30", .cpus = (const CPU[]) { { - .name = "5", + .name = "7.16", .cpu_type = CPU_V30, .fpus = fpus_80186, - .rspeed = 5000000, + .rspeed = 7159092, .multi = 1, .voltage = 5000, .edx_reset = 0, @@ -944,6 +961,23 @@ const cpu_family_t cpu_families[] = { .cache_write_cycles = 0, .atclk_div = 1 }, + { + .name = "9.54", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 9545456, + .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_V30, diff --git a/src/device/isarom.c b/src/device/isarom.c index cdf5a61c6..823bfcbe1 100644 --- a/src/device/isarom.c +++ b/src/device/isarom.c @@ -26,9 +26,14 @@ #include <86box/nvr.h> #include <86box/isarom.h> -#define ISAROM_CARD 0 -#define ISAROM_CARD_DUAL 1 -#define ISAROM_CARD_QUAD 2 +enum { + ISAROM_CARD = 0, + ISAROM_CARD_DUAL, + ISAROM_CARD_QUAD, + ISAROM_CARD_LBA_ENHANCER +}; + +#define BIOS_LBA_ENHANCER "roms/hdd/misc/lbaenhancer.bin" #ifdef ENABLE_ISAROM_LOG int isarom_do_log = ENABLE_ISAROM_LOG; @@ -56,7 +61,7 @@ typedef struct isarom_t { uint32_t size; uint32_t len; char nvr_path[64]; - uint8_t wp; + uint8_t writable; } socket[4]; uint8_t inst; uint8_t type; @@ -65,11 +70,14 @@ typedef struct 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; + switch (type) { + case ISAROM_CARD_DUAL: + return 2; + case ISAROM_CARD_QUAD: + return 4; + default: + return 1; + } } static inline void @@ -92,12 +100,13 @@ isarom_close(void *priv) if (!priv) return; - for (uint8_t i = 0; i < get_limit(dev->type); i++) - if (dev->socket[i].rom.rom) { + for (uint8_t i = 0; i < get_limit(dev->type); i++) { + if (dev->socket[i].writable) { 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); } @@ -115,32 +124,42 @@ isarom_init(const device_t *info) 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 str[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); + snprintf(str, sizeof(str), "bios_addr%s", suffix); + dev->socket[i].addr = device_get_config_hex20(str); - 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; + switch (dev->type) { + case ISAROM_CARD_LBA_ENHANCER: + dev->socket[i].fn = BIOS_LBA_ENHANCER; + dev->socket[i].size = 0x4000; + break; - isarom_log("isarom[%u]: socket %u: addr=0x%05X size=%u wp=%u fn=%s\n", + default: + snprintf(str, sizeof(str), "bios_fn%s", suffix); + dev->socket[i].fn = device_get_config_string(str); + + snprintf(str, sizeof(str), "bios_size%s", suffix); + dev->socket[i].size = device_get_config_int(str); + + snprintf(str, sizeof(str), "rom_writes_enabled%s", suffix); + if (device_get_config_int(str)) + dev->socket[i].writable = 1; + break; + } + + /* 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 > 0) ? ((dev->socket[i].size - 1) | MEM_GRANULARITY_MASK) : 0; + + isarom_log("isarom[%u]: socket %u: addr=0x%05X size=%u writable=%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)"); + dev->socket[i].writable, dev->socket[i].fn ? dev->socket[i].fn : "(null)"); - if (dev->socket[i].addr != 0 && 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, @@ -151,7 +170,7 @@ isarom_init(const device_t *info) isarom_log("isarom[%u]: ROM initialized for socket %u\n", dev->inst, i); - if (dev->socket[i].wp) { + if (dev->socket[i].writable) { 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"); @@ -168,6 +187,12 @@ isarom_init(const device_t *info) return dev; } +static int +isarom_lba_enhancer_available(void) +{ + return rom_present(BIOS_LBA_ENHANCER); +} + #define BIOS_FILE_FILTER "ROM files (*.bin *.rom)|*.bin,*.rom" #define BIOS_ADDR_SELECTION { \ @@ -444,7 +469,7 @@ static const device_config_t isarom_quad_config[] = { .type = CONFIG_FNAME, .default_string = NULL, .default_int = 0, - .file_filter = "ROM files (*.bin *.rom)|*.bin,*.rom", + .file_filter = BIOS_FILE_FILTER, .spinner = { 0 }, .selection = { }, .bios = { { 0 } } @@ -528,6 +553,29 @@ static const device_config_t isarom_quad_config[] = { }, { .name = "", .description = "", .type = CONFIG_END } }; + +static const device_config_t lba_enhancer_config[] = { + { + .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 } +}; // clang-format on static const device_t isarom_device = { @@ -572,15 +620,30 @@ static const device_t isarom_quad_device = { .config = isarom_quad_config }; +static const device_t lba_enhancer_device = { + .name = "Vision Systems LBA Enhancer", + .internal_name = "lba_enhancer", + .flags = DEVICE_ISA, + .local = ISAROM_CARD_LBA_ENHANCER, + .init = isarom_init, + .close = isarom_close, + .reset = NULL, + .available = isarom_lba_enhancer_available, + .speed_changed = NULL, + .force_redraw = NULL, + .config = lba_enhancer_config +}; + static const struct { const device_t *dev; } boards[] = { // clang-format off - { &device_none }, - { &isarom_device }, - { &isarom_dual_device }, - { &isarom_quad_device }, - { NULL } + { &device_none }, + { &isarom_device }, + { &isarom_dual_device }, + { &isarom_quad_device }, + { &lba_enhancer_device }, + { NULL } // clang-format on }; diff --git a/src/device/lpt.c b/src/device/lpt.c index 11afc04f9..4c5578490 100644 --- a/src/device/lpt.c +++ b/src/device/lpt.c @@ -626,34 +626,29 @@ lpt_set_ext(const int port, const uint8_t 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); + if (lpt_ports[port].enabled) 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); + if (lpt_ports[port].enabled) 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); + if (lpt_ports[port].enabled) lpt_ports[port].lv2 = lv2; - lpt_port_setup(port, addr); - } +} + +void +lpt_set_fifo_threshold(const int port, const int threshold) +{ + if (lpt_ports[port].enabled) + fifo_set_trigger_len(lpt_ports[port].fifo, threshold); } void @@ -778,19 +773,19 @@ void lpt_port_setup(const int i, const uint16_t port) { if (lpt_ports[i].enabled) { - if (lpt_ports[i].addr != 0xffff) { + if ((lpt_ports[i].addr != 0x0000) && (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) { + if ((port != 0x0000) && (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]); + io_sethandler(port + 0x0003, 0x0005, 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]); + io_sethandler(port + 0x0404, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); } } lpt_ports[i].addr = port; diff --git a/src/device/mouse.c b/src/device/mouse.c index 0bf87934d..2337c041f 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -83,24 +83,25 @@ 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_mssystems_bus_device }, - { &mouse_msserial_device }, - { &mouse_ltserial_device }, - { &mouse_ps2_device }, + { &mouse_mssystems_device }, + { &mouse_mssystems_bus_device }, + { &mouse_msserial_device }, + { &mouse_msserial_ballpoint_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 7505cf3a3..341ddefe7 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -50,7 +50,7 @@ enum { FORMAT_MM_SERIES = 0x13, FORMAT_PB_3BYTE, FORMAT_PB_5BYTE, - FORMAT_MSYSTEMS = 0x15, /* Alias for FORMAT_PB_5BYTE. */ + FORMAT_MSYSTEMS = 0x15, /* Alias for FORMAT_PB_5BYTE. */ FORMAT_MS, FORMAT_HEX, FORMAT_MS_4BYTE, @@ -59,45 +59,46 @@ enum { }; typedef struct mouse_t { - const char *name; /* name of this device */ + const char *name; /* name of this device */ - uint8_t id[252]; - uint8_t buf[256]; + uint8_t id[252]; + uint8_t buf[256]; - uint8_t flags; /* device flags */ - uint8_t but; - uint8_t rts_toggle; - uint8_t status; - uint8_t format; - uint8_t prompt; + uint8_t flags; /* device flags */ + uint8_t but; + uint8_t rts_toggle; + uint8_t status; + uint8_t format; + uint8_t prompt; - uint8_t continuous; - uint8_t ib; - uint8_t command; - uint8_t buf_len; - uint8_t report_mode; - uint8_t id_len; - uint8_t buf_pos; - uint8_t rev; + uint8_t continuous; + uint8_t ib; + uint8_t command; + uint8_t buf_len; + uint8_t report_mode; + uint8_t id_len; + uint8_t buf_pos; + uint8_t rev; - int8_t type; /* type of this device */ - int8_t port; + int8_t type; /* type of this device */ + int8_t port; - int state; + int state; - int bps; - int rps; + int bps; + int default_bps; + int rps; - double transmit_period; - double report_period; - double cur_period; - double min_bit_period; - double acc_time; - double host_transmit_period; + double transmit_period; + double report_period; + double cur_period; + double min_bit_period; + double acc_time; + double host_transmit_period; - pc_timer_t timer; + pc_timer_t timer; - serial_t * serial; + serial_t *serial; } mouse_t; #define FLAG_INPORT 0x80 /* device is MS InPort */ @@ -128,7 +129,7 @@ mouse_serial_log(const char *fmt, ...) static void sermouse_set_period(mouse_t *dev, double period) { - dev->cur_period = period; /* Needed for the recalculation of the timings. */ + dev->cur_period = period; /* Needed for the recalculation of the timings. */ timer_stop(&dev->timer); @@ -160,7 +161,7 @@ sermouse_transmit_byte(mouse_t *dev, int do_next) static void sermouse_transmit(mouse_t *dev, int len, int from_report, int to_report) { - dev->state = to_report ? STATE_TRANSMIT_REPORT : STATE_TRANSMIT; + dev->state = to_report ? STATE_TRANSMIT_REPORT : STATE_TRANSMIT; dev->buf_pos = 0; dev->buf_len = len; @@ -186,7 +187,7 @@ sermouse_report_msystems(mouse_t *dev) { int delta_x = 0; int delta_y = 0; - int b = mouse_get_buttons_ex(); + int b = mouse_get_buttons_ex(); mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0); @@ -195,12 +196,12 @@ sermouse_report_msystems(mouse_t *dev) if (dev->but >= 3) dev->buf[0] |= (b & 0x04) ? 0x00 : 0x02; /* middle button */ else - dev->buf[0] |= 0x02; /* middle button */ + dev->buf[0] |= 0x02; /* middle button */ dev->buf[0] |= (b & 0x02) ? 0x00 : 0x01; /* right button */ dev->buf[1] = delta_x; dev->buf[2] = delta_y; - dev->buf[3] = delta_x; /* same as byte 1 */ - dev->buf[4] = delta_y; /* same as byte 2 */ + dev->buf[3] = delta_x; /* same as byte 1 */ + dev->buf[4] = delta_y; /* same as byte 2 */ return 5; } @@ -210,7 +211,7 @@ sermouse_report_3bp(mouse_t *dev) { int delta_x = 0; int delta_y = 0; - int b = mouse_get_buttons_ex(); + int b = mouse_get_buttons_ex(); mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0); @@ -218,7 +219,7 @@ sermouse_report_3bp(mouse_t *dev) dev->buf[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */ if (dev->but >= 3) dev->buf[0] |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ - dev->buf[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ + dev->buf[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ dev->buf[1] = delta_x; dev->buf[2] = delta_y; @@ -230,7 +231,7 @@ sermouse_report_mmseries(mouse_t *dev) { int delta_x = 0; int delta_y = 0; - int b = mouse_get_buttons_ex(); + int b = mouse_get_buttons_ex(); mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -127, 127, 1, 0); @@ -243,7 +244,7 @@ sermouse_report_mmseries(mouse_t *dev) dev->buf[0] |= (b & 0x01) ? 0x04 : 0x00; /* left button */ if (dev->but >= 3) dev->buf[0] |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ - dev->buf[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ + dev->buf[0] |= (b & 0x02) ? 0x01 : 0x00; /* right button */ dev->buf[1] = ABS(delta_x) & 0x7f; dev->buf[2] = ABS(delta_y) & 0x7f; mouse_serial_log("MM series mouse report: %02X %02X %02X\n", dev->buf[0], dev->buf[1], dev->buf[2]); @@ -256,7 +257,7 @@ sermouse_report_bp1(mouse_t *dev, int abs) { int delta_x = 0; int delta_y = 0; - int b = mouse_get_buttons_ex(); + int b = mouse_get_buttons_ex(); mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -2048, 2047, 1, abs); @@ -264,7 +265,7 @@ sermouse_report_bp1(mouse_t *dev, int abs) dev->buf[0] |= (b & 0x01) ? 0x10 : 0x00; /* left button */ if (dev->but >= 3) dev->buf[0] |= (b & 0x04) ? 0x08 : 0x00; /* middle button */ - dev->buf[0] |= (b & 0x02) ? 0x04 : 0x00; /* right button */ + dev->buf[0] |= (b & 0x02) ? 0x04 : 0x00; /* right button */ dev->buf[1] = (delta_x & 0x3f); dev->buf[2] = ((delta_x >> 6) & 0x3f); dev->buf[3] = (delta_y & 0x3f); @@ -277,17 +278,17 @@ static uint8_t sermouse_report_ms(mouse_t *dev) { uint8_t len; - int delta_x = 0; - int delta_y = 0; - int delta_z = 0; - int b = mouse_get_buttons_ex(); + int delta_x = 0; + int delta_y = 0; + int delta_z = 0; + int b = mouse_get_buttons_ex(); mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 0, 0); mouse_subtract_z(&delta_z, -8, 7, 1); dev->buf[0] = 0x40; - dev->buf[0] |= (((delta_y >> 6) & 0x03) << 2); - dev->buf[0] |= ((delta_x >> 6) & 0x03); + dev->buf[0] |= ((((delta_y & 0xFF) >> 6) & 0x03) << 2); + dev->buf[0] |= (((delta_x & 0xFF) >> 6) & 0x03); if (b & 0x01) dev->buf[0] |= 0x20; if (b & 0x02) @@ -295,7 +296,16 @@ sermouse_report_ms(mouse_t *dev) dev->buf[1] = delta_x & 0x3f; dev->buf[2] = delta_y & 0x3f; mouse_serial_log("Microsoft serial mouse report: %02X %02X %02X\n", dev->buf[0], dev->buf[1], dev->buf[2]); - if (dev->but == 3) { + if (dev->type == MOUSE_TYPE_MSBPOINT) { + len = 4; + dev->buf[3] = 0; + if (b & 0x4) + dev->buf[3] |= 0x8; + if (b & 0x8) + dev->buf[3] |= 0x4; + dev->buf[3] |= !!(delta_y < 0) ? 0x2 : 0; + dev->buf[3] |= !!(delta_x < 0) ? 0x1 : 0; + } else if (dev->but == 3) { len = 3; if (dev->format == FORMAT_MS) { if (b & 0x04) { @@ -325,18 +335,18 @@ sermouse_report_ms(mouse_t *dev) static uint8_t sermouse_report_hex(mouse_t *dev) { - char ret[6] = { 0, 0, 0, 0, 0, 0 }; - uint8_t but = 0x00; - int delta_x = 0; - int delta_y = 0; - int b = mouse_get_buttons_ex(); + char ret[6] = { 0, 0, 0, 0, 0, 0 }; + uint8_t but = 0x00; + int delta_x = 0; + int delta_y = 0; + int b = mouse_get_buttons_ex(); mouse_subtract_coords(&delta_x, &delta_y, NULL, NULL, -128, 127, 1, 0); but |= (b & 0x01) ? 0x04 : 0x00; /* left button */ if (dev->but >= 3) but |= (b & 0x04) ? 0x02 : 0x00; /* middle button */ - but |= (b & 0x02) ? 0x01 : 0x00; /* right button */ + but |= (b & 0x02) ? 0x01 : 0x00; /* right button */ sprintf(ret, "%01X%02X%02X", but & 0x0f, (int8_t) delta_x, (int8_t) delta_y); @@ -441,14 +451,14 @@ ltsermouse_set_report_period(mouse_t *dev, int rps) sermouse_set_period(dev, 0.0); dev->report_period = 0.0; - dev->continuous = 1; + dev->continuous = 1; } else { #if 0 if (rps > dev->max_rps) rps = dev->max_rps; #endif - dev->continuous = 0; + dev->continuous = 0; dev->report_period = 1000000.0 / ((double) rps); /* Actual spacing between reports. */ } @@ -473,18 +483,19 @@ static void ltsermouse_switch_baud_rate(mouse_t *dev, int next_state) { double word_lens[FORMATS_NUM] = { - [FORMAT_BP1_ABS] = 7.0 + 1.0, /* 7 data bits + even parity */ - [FORMAT_BP1_REL] = 7.0 + 1.0, /* 7 data bits + even parity */ - [FORMAT_MM_SERIES] = 8.0 + 1.0, /* 8 data bits + odd parity */ - [FORMAT_PB_3BYTE] = 8.0, /* 8 data bits + no parity */ - [FORMAT_PB_5BYTE] = 8.0, /* 8 data bits + no parity */ - [FORMAT_MS] = 7.0, /* 7 datas bits + no parity */ - [FORMAT_HEX] = 8.0, /* 8 data bits + no parity */ - [FORMAT_MS_4BYTE] = 7.0, /* 7 datas bits + no parity */ - [FORMAT_MS_WHEEL] = 7.0 }; /* 7 datas bits + no parity */ + [FORMAT_BP1_ABS] = 7.0 + 1.0, /* 7 data bits + even parity */ + [FORMAT_BP1_REL] = 7.0 + 1.0, /* 7 data bits + even parity */ + [FORMAT_MM_SERIES] = 8.0 + 1.0, /* 8 data bits + odd parity */ + [FORMAT_PB_3BYTE] = 8.0, /* 8 data bits + no parity */ + [FORMAT_PB_5BYTE] = 8.0, /* 8 data bits + no parity */ + [FORMAT_MS] = 7.0, /* 7 datas bits + no parity */ + [FORMAT_HEX] = 8.0, /* 8 data bits + no parity */ + [FORMAT_MS_4BYTE] = 7.0, /* 7 datas bits + no parity */ + [FORMAT_MS_WHEEL] = 7.0 /* 7 datas bits + no parity */ + }; double word_len = word_lens[dev->format]; - word_len += 1.0 + 2.0; /* 1 start bit + 2 stop bits */ + word_len += 1.0 + 2.0; /* 1 start bit + 2 stop bits */ #if 0 dev->max_rps = (int) floor(((double) dev->bps) / (word_len * num_words)); @@ -531,18 +542,19 @@ sermouse_next_state(mouse_t *dev) static void ltsermouse_process_command(mouse_t *dev) { - int cmd_to_rps[9] = { 10, 20, 35, 70, 150, 0, -1, 100, 50 }; - int b; + int cmd_to_rps[9] = { 10, 20, 35, 70, 150, 0, -1, 100, 50 }; + int b; uint8_t format_codes[FORMATS_NUM] = { - [FORMAT_BP1_ABS] = 0x0c, - [FORMAT_BP1_REL] = 0x06, - [FORMAT_MM_SERIES] = 0x0a, - [FORMAT_PB_3BYTE] = 0x00, - [FORMAT_PB_5BYTE] = 0x02, - [FORMAT_MS] = 0x0e, - [FORMAT_HEX] = 0x04, - [FORMAT_MS_4BYTE] = 0x08, /* Guess */ - [FORMAT_MS_WHEEL] = 0x08 }; /* Guess */ + [FORMAT_BP1_ABS] = 0x0c, + [FORMAT_BP1_REL] = 0x06, + [FORMAT_MM_SERIES] = 0x0a, + [FORMAT_PB_3BYTE] = 0x00, + [FORMAT_PB_5BYTE] = 0x02, + [FORMAT_MS] = 0x0e, + [FORMAT_HEX] = 0x04, + [FORMAT_MS_4BYTE] = 0x08, /* Guess */ + [FORMAT_MS_WHEEL] = 0x08 /* Guess */ + }; const char *copr = "\r\n(C) " COPYRIGHT_YEAR " 86Box, Revision 3.0"; mouse_serial_log("ltsermouse_process_command(): %02X\n", dev->ib); @@ -551,7 +563,7 @@ ltsermouse_process_command(mouse_t *dev) switch (dev->command) { case 0x20: /* Auto Baud Selection */ - dev->bps = (int) floor(1000000.0 / dev->host_transmit_period); + dev->bps = (int) floor(1000000.0 / dev->host_transmit_period); dev->transmit_period = dev->host_transmit_period; dev->buf[0] = 0x06; @@ -569,7 +581,7 @@ ltsermouse_process_command(mouse_t *dev) case 0x4e: case 0x4f: dev->report_mode = dev->command; - dev->rps = cmd_to_rps[dev->command - 0x4a]; + dev->rps = cmd_to_rps[dev->command - 0x4a]; ltsermouse_update_report_period(dev); break; @@ -593,13 +605,13 @@ ltsermouse_process_command(mouse_t *dev) /* Absolute Bit Pad One Packed Binary Format */ mouse_clear_coords(); fallthrough; - case 0x42: /* Relative Bit Pad One Packed Binary Format */ - case 0x53: /* MM Series Data Format */ - case 0x54: /* Three Byte Packed Binary Format */ - case 0x55: /* Five Byte Packed Binary Format (Mouse Systems-compatible) */ - case 0x56: /* Microsoft Compatible Format */ - case 0x57: /* Hexadecimal Format */ - case 0x58: /* Microsoft Compatible Format (3+1 byte 3-button, from the FreeBSD source code) */ + case 0x42: /* Relative Bit Pad One Packed Binary Format */ + case 0x53: /* MM Series Data Format */ + case 0x54: /* Three Byte Packed Binary Format */ + case 0x55: /* Five Byte Packed Binary Format (Mouse Systems-compatible) */ + case 0x56: /* Microsoft Compatible Format */ + case 0x57: /* Hexadecimal Format */ + case 0x58: /* Microsoft Compatible Format (3+1 byte 3-button, from the FreeBSD source code) */ if ((dev->rev >= 0x02) && ((dev->command != 0x58) || (dev->rev > 0x04))) { dev->format = dev->command & 0x1f; ltsermouse_switch_baud_rate(dev, sermouse_next_state(dev)); @@ -620,7 +632,7 @@ ltsermouse_process_command(mouse_t *dev) break; case 0x05: /* Diagnostic */ - b = mouse_get_buttons_ex(); + b = mouse_get_buttons_ex(); dev->buf[0] = ((b & 0x01) << 2) | ((b & 0x06) >> 1); dev->buf[1] = dev->buf[2] = 0x00; sermouse_transmit(dev, 3, 0, 0); @@ -630,7 +642,7 @@ ltsermouse_process_command(mouse_t *dev) if (dev->rev >= 0x20) { /* Format and Revision Number */ dev->buf[0] = format_codes[dev->format]; - dev->buf[0] |= 0x10; /* Revision 3.0, 0x00 would be Revision 2.0 */ + dev->buf[0] |= 0x10; /* Revision 3.0, 0x00 would be Revision 2.0 */ sermouse_transmit(dev, 1, 0, 0); } break; @@ -676,7 +688,7 @@ ltsermouse_process_data(mouse_t *dev) { mouse_serial_log("ltsermouse_process_data(): %02X (command = %02X)\n", dev->ib, dev->command); - switch(dev->command) { + switch (dev->command) { case 0x2a: switch (dev->ib) { default: @@ -707,23 +719,30 @@ sermouse_reset(mouse_t *dev, int callback) { sermouse_set_period(dev, 0.0); - dev->bps = 1200; - dev->rps = 0; + if (dev->default_bps) + dev->bps = dev->default_bps; + else + dev->bps = 1200; + dev->rps = 0; dev->prompt = 0; if (dev->id[0] == 'H') dev->format = FORMAT_MSYSTEMS; - else switch (dev->but) { - default: - case 2: - dev->format = FORMAT_MS; - break; - case 3: - dev->format = (dev->type == MOUSE_TYPE_LT3BUTTON) ? FORMAT_MS : FORMAT_MS_4BYTE; - break; - case 4: - dev->format = FORMAT_MS_WHEEL; - break; - } + else + switch (dev->but) { + default: + case 2: + dev->format = FORMAT_MS; + break; + case 3: + dev->format = (dev->type == MOUSE_TYPE_LT3BUTTON) ? FORMAT_MS : FORMAT_MS_4BYTE; + break; + case 4: + dev->format = FORMAT_MS_WHEEL; + break; + case 5: + dev->format = FORMAT_MS; + break; + } ltsermouse_switch_baud_rate(dev, callback ? STATE_TRANSMIT : STATE_IDLE); } @@ -840,7 +859,7 @@ sermouse_close(void *priv) static void * sermouse_init(const device_t *info) { - mouse_t *dev; + mouse_t *dev = (mouse_t *) calloc(1, sizeof(mouse_t)); 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, @@ -850,34 +869,40 @@ sermouse_init(const device_t *info) 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); + 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"); - dev->rev = device_get_config_int("revision"); + dev->but = (info->local == MOUSE_TYPE_MSBPOINT) ? 5 : device_get_config_int("buttons"); - if (info->local == 0) - dev->rts_toggle = 1; + if ((info->local == 0) || (info->local == MOUSE_TYPE_MSBPOINT)) + dev->rts_toggle = 1; else - dev->rts_toggle = device_get_config_int("rts_toggle"); + dev->rts_toggle = device_get_config_int("rts_toggle"); if (dev->but > 2) dev->flags |= FLAG_3BTN; - if (info->local == MOUSE_TYPE_MSYSTEMS || info->local == MOUSE_TYPE_MSYSTEMSB) { - dev->format = 0; - dev->type = info->local; - dev->id_len = 1; - dev->id[0] = 'H'; + if (info->local == MOUSE_TYPE_MSBPOINT) { + dev->format = 7; + dev->status = 0x0f; + dev->type = MOUSE_TYPE_MSBPOINT; + dev->id_len = 1; + dev->id[0] = 'B'; + dev->flags &= ~FLAG_3BTN; + } else if ((info->local == MOUSE_TYPE_MSYSTEMS) || (info->local == MOUSE_TYPE_MSYSTEMSB)) { + dev->format = 0; + dev->type = info->local; + dev->id_len = 1; + dev->id[0] = 'H'; } else { - dev->format = 7; - dev->status = 0x0f; - dev->id_len = 1; - dev->id[0] = 'M'; - if (info->local) - dev->rev = device_get_config_int("revision"); + dev->format = 7; + dev->status = 0x0f; + dev->id_len = 1; + dev->id[0] = 'M'; + if (info->local == 1) // Logitech Serial Mouse + dev->rev = device_get_config_int("revision"); + dev->default_bps = device_get_config_int("default_baud"); switch (dev->but) { default: case 2: @@ -900,8 +925,8 @@ sermouse_init(const device_t *info) 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; - dev_write = (info->local == 1) ? ltsermouse_write : NULL; + rcr_callback = dev->rts_toggle ? sermouse_callback : NULL; + dev_write = (info->local == 1) ? ltsermouse_write : NULL; transmit_period_callback = (info->local == 1) ? ltsermouse_transmit_period : NULL; dev->serial = serial_attach_ex(dev->port, rcr_callback, dev_write, @@ -923,25 +948,28 @@ sermouse_init(const device_t *info) return dev; } +#define SERMOUSE_PORT_CONFIG_COMMON \ + { \ + .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 } } \ + } + static const device_config_t msssermouse_config[] = { - // clang-format off - { - .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 } } - }, + // clang-format off + SERMOUSE_PORT_CONFIG_COMMON, { .name = "buttons", .description = "Buttons", @@ -969,7 +997,7 @@ static const device_config_t msssermouse_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; static const device_config_t mssbusmouse_config[] = { @@ -1042,27 +1070,11 @@ static const device_config_t mssbusmouse_config[] = { }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on - }; +}; static const device_config_t mssermouse_config[] = { - // clang-format off - { - .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 } } - }, + // clang-format off + SERMOUSE_PORT_CONFIG_COMMON, { .name = "buttons", .description = "Buttons", @@ -1080,28 +1092,19 @@ static const device_config_t mssermouse_config[] = { .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on +}; + +static const device_config_t msballpoint_config[] = { + // clang-format off + SERMOUSE_PORT_CONFIG_COMMON, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on }; static const device_config_t ltsermouse_config[] = { - // clang-format off - { - .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 } } - }, + // clang-format off + SERMOUSE_PORT_CONFIG_COMMON, { .name = "buttons", .description = "Buttons", @@ -1134,19 +1137,36 @@ static const device_config_t ltsermouse_config[] = { }, .bios = { { 0 } } }, + { + .name = "default_baud", + .description = "Default Baud rate", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 1200, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "1200", .value = 1200 }, + { .description = "2400", .value = 2400 }, + { .description = "4800", .value = 4800 }, + { .description = "9600", .value = 9600 }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "rts_toggle", .description = "RTS toggle", .type = CONFIG_BINARY, .default_string = NULL, - .default_int = 0, + .default_int = 1, .file_filter = NULL, .spinner = { 0 }, .selection = { { 0 } }, .bios = { { 0 } } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; const device_t mouse_mssystems_device = { @@ -1191,6 +1211,20 @@ const device_t mouse_msserial_device = { .config = mssermouse_config }; +const device_t mouse_msserial_ballpoint_device = { + .name = "Microsoft Serial BallPoint", + .internal_name = "msballpoint", + .flags = DEVICE_COM, + .local = MOUSE_TYPE_MSBPOINT, + .init = sermouse_init, + .close = sermouse_close, + .reset = NULL, + .available = NULL, + .speed_changed = sermouse_speed_changed, + .force_redraw = NULL, + .config = msballpoint_config +}; + const device_t mouse_ltserial_device = { .name = "Logitech Serial Mouse", .internal_name = "ltserial", diff --git a/src/device/novell_cardkey.c b/src/device/novell_cardkey.c index 08334e751..edc32b879 100644 --- a/src/device/novell_cardkey.c +++ b/src/device/novell_cardkey.c @@ -37,24 +37,29 @@ novell_cardkey_read(uint16_t port, void *priv) novell_cardkey_t* cardkey = (novell_cardkey_t*)priv; uint8_t val = 0x00; switch (port) { + /* Byte 5 high nibble + byte 4 high nibble */ case 0x23A: - val = (((cardkey->serial_number_str[11] > 'A') ? ((cardkey->serial_number_str[11] - 'A') + 10) : (cardkey->serial_number_str[11] - '0')) << 4) | (((cardkey->serial_number_str[9] > 'A') ? ((cardkey->serial_number_str[9] - 'A') + 10) : (cardkey->serial_number_str[9] - '0')) << 4); - break; - case 0x23B: val = (((cardkey->serial_number_str[10] > 'A') ? ((cardkey->serial_number_str[10] - 'A') + 10) : (cardkey->serial_number_str[10] - '0')) << 4) | (((cardkey->serial_number_str[8] > 'A') ? ((cardkey->serial_number_str[8] - 'A') + 10) : (cardkey->serial_number_str[8] - '0')) << 4); break; - + /* Byte 5 low nibble + byte 4 low nibble */ + case 0x23B: + val = (((cardkey->serial_number_str[11] > 'A') ? ((cardkey->serial_number_str[11] - 'A') + 10) : (cardkey->serial_number_str[11] - '0')) << 4) | (((cardkey->serial_number_str[9] > 'A') ? ((cardkey->serial_number_str[9] - 'A') + 10) : (cardkey->serial_number_str[9] - '0')) << 4); + break; + /* Byte 2 low nibble + byte 1 low nibble */ case 0x23C: - val = ((cardkey->serial_number_str[4] - '0') << 4) | ((cardkey->serial_number_str[2] - '0')); + val = ((cardkey->serial_number_str[5] - '0') << 4) | ((cardkey->serial_number_str[3] - '0')); break; + /* Byte 0 high nibble + byte 3 low nibble*/ case 0x23D: - val = ((cardkey->serial_number_str[1] - '0') << 4) | ((cardkey->serial_number_str[6] - '0')); - break; - case 0x23E: val = ((cardkey->serial_number_str[0] - '0') << 4) | ((cardkey->serial_number_str[7] - '0')); break; + /* Byte 0 low nibble + byte 3 high nibble */ + case 0x23E: + val = ((cardkey->serial_number_str[1] - '0') << 4) | ((cardkey->serial_number_str[6] - '0')); + break; + /* Byte 1 high nibble + byte 2 high nibble*/ case 0x23F: - val = ((cardkey->serial_number_str[3] - '0') << 4) | ((cardkey->serial_number_str[5] - '0')); + val = ((cardkey->serial_number_str[2] - '0') << 4) | ((cardkey->serial_number_str[4] - '0')); break; } return val ^ 0xFF; @@ -110,7 +115,7 @@ static const device_config_t keycard_config[] = { const device_t novell_keycard_device = { .name = "Novell NetWare 2.x Key Card", - .internal_name = "mssystems", + .internal_name = "novellkeycard", .flags = DEVICE_ISA, .local = 0, .init = novell_cardkey_init, diff --git a/src/disk/CMakeLists.txt b/src/disk/CMakeLists.txt index bdbb9e74c..48d9e61ff 100644 --- a/src/disk/CMakeLists.txt +++ b/src/disk/CMakeLists.txt @@ -35,7 +35,6 @@ add_library(hdd OBJECT hdc_ide_sff8038i.c hdc_ide_um8673f.c hdc_ide_w83769f.c - lba_enhancer.c ) add_library(zip OBJECT zip.c) diff --git a/src/disk/lba_enhancer.c b/src/disk/lba_enhancer.c deleted file mode 100644 index ef9e167d3..000000000 --- a/src/disk/lba_enhancer.c +++ /dev/null @@ -1,100 +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. - * - * Vision Systems LBA Enhancer emulation. - * - * - * - * Authors: Cacodemon345 - * - * Copyright 2024 Cacodemon345 - */ - -#include -#include -#include -#include -#include -#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/plat_unused.h> - -typedef struct lba_enhancer_t -{ - rom_t rom; -} lba_enhancer_t; - -#define BIOS_LBA_ENHANCER "roms/hdd/misc/lbaenhancer.bin" - -void -lba_enhancer_close(void* priv) -{ - free(priv); - - return; -} - -void * -lba_enhancer_init(UNUSED(const device_t *info)) -{ - lba_enhancer_t *dev = (lba_enhancer_t *) calloc(1, sizeof(lba_enhancer_t)); - - rom_init(&dev->rom, BIOS_LBA_ENHANCER, - device_get_config_hex20("bios_addr"), 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - return dev; -} - -static int -lba_enhancer_available(void) -{ - return rom_present(BIOS_LBA_ENHANCER); -} - -// clang-format off -static const device_config_t lba_enhancer_config[] = { - { - .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 } -}; -// clang-format on - -const device_t lba_enhancer_device = { - .name = "Vision Systems LBA Enhancer", - .internal_name = "lba_enhancer", - .flags = DEVICE_ISA16, - .local = 0, - .init = lba_enhancer_init, - .close = lba_enhancer_close, - .reset = NULL, - .available = lba_enhancer_available, - .speed_changed = NULL, - .force_redraw = NULL, - .config = lba_enhancer_config -}; diff --git a/src/floppy/fdc_compaticard.c b/src/floppy/fdc_compaticard.c index 741105927..cc438ddf6 100644 --- a/src/floppy/fdc_compaticard.c +++ b/src/floppy/fdc_compaticard.c @@ -214,7 +214,7 @@ static const device_config_t compaticard_ii_config[] = { }, { .name = "dma", - .description = "DMA channel", + .description = "DMA", .type = CONFIG_SELECTION, .default_string = NULL, .default_int = 2, @@ -272,7 +272,7 @@ static const device_config_t compaticard_iv_config[] = { }, { .name = "dma", - .description = "DMA channel", + .description = "DMA", .type = CONFIG_SELECTION, .default_string = NULL, .default_int = 2, diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 31811069f..1623f932a 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -212,18 +212,9 @@ int fdd_get_from_internal_name(char *s) { int c = 0; - char *n; - - /* TODO: Remove this once the migration period is over. */ - if (!strcmp(s, "525_2hd_ps2")) - n = "525_2hd"; - else if (!strcmp(s, "35_2hd_ps2")) - n = "35_2hd"; - else - n = s; while (strlen(drive_types[c].internal_name)) { - if (!strcmp((char *) drive_types[c].internal_name, n)) + if (!strcmp((char *) drive_types[c].internal_name, s)) return c; c++; } diff --git a/src/game/gameport.c b/src/game/gameport.c index 8ae1c7d25..3025ee5eb 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -15,7 +15,7 @@ * * Copyright 2016-2022 Miran Grca. * Copyright 2008-2018 Sarah Walker. - * Copyright 2021 RichardG. + * Copyright 2021 RichardG. * Copyright 2021-2025 Jasmine Iwanek. */ #include @@ -90,11 +90,18 @@ static const struct { } joysticks[] = { { &joystick_none }, { &joystick_2axis_2button }, + { &joystick_2button_gamepad }, + { &joystick_2button_flight_yoke }, { &joystick_2axis_4button }, + { &joystick_4button_gamepad }, + { &joystick_4button_flight_yoke }, { &joystick_2axis_6button }, { &joystick_2axis_8button }, { &joystick_3axis_2button }, + { &joystick_2button_yoke_throttle }, { &joystick_3axis_4button }, + { &joystick_win95_steering_wheel }, // Temp + { &joystick_4button_yoke_throttle }, { &joystick_4axis_4button }, { &joystick_ch_flightstick_pro }, { &joystick_ch_flightstick_pro_ch_pedals }, @@ -245,7 +252,7 @@ gameport_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), void *priv) /* Notify the interface. */ joystick->intf->write(joystick->dat); - cycles -= ISA_CYCLES(8); + cycles -= ISA_CYCLES((8 << is_pcjr)); } static uint8_t @@ -261,7 +268,7 @@ gameport_read(UNUSED(uint16_t addr), void *priv) /* Merge axis state with button state. */ uint8_t ret = joystick->state | joystick->intf->read(joystick->dat); - cycles -= ISA_CYCLES(8); + cycles -= ISA_CYCLES((8 << is_pcjr)); return ret; } @@ -299,6 +306,9 @@ gameport_remap(void *priv, uint16_t address) gameport_t *dev = (gameport_t *) priv; gameport_t *other_dev; + if (dev == NULL) + return; + if (dev->addr) { /* Remove this port from the active ports list. */ if (active_gameports == dev) { diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index 5f200cb98..8136935ea 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -8,13 +8,14 @@ * * Implementation of a standard joystick. * - * - * * Authors: Miran Grca, * Sarah Walker, + * Miran Grca, + * Jasmine Iwanek, * * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. + * 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 @@ -147,6 +148,40 @@ joystick_standard_read_axis_4button(UNUSED(void *priv), int axis) } } +#if 0 +// For later use +static int +joystick_standard_read_axis_with_pov(UNUSED(void *priv), int axis) +{ + if (!JOYSTICK_PRESENT(0, 0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: // X-axis + return joystick_state[0][0].axis[0]; + case 1: // Y-axis + return joystick_state[0][0].axis[1]; + case 2: // POV Hat (mapped to the 3rd logical axis, index 2) + if (joystick_state[0][0].pov[0] == -1) + return 32767; // Centered/No input (as per tm_fcs_rcs_read_axis example) + if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45) + return -32768; // Up + if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135) + return -16384; // Up-Right (example value, matches tm_fcs_rcs_read_axis) + if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225) + return 0; // Right/Left (example, matches tm_fcs_rcs_read_axis) + if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315) + return 16384; // Down-Left (example value, matches tm_fcs_rcs_read_axis) + return 0; // Fallback + case 3: // This case might be used for a Z-axis if present, or can return 0 if not. + // For gamepads with only X/Y and POV, this will likely be unused or return 0. + return 0; + default: + return 0; + } +} +#endif + static int joystick_standard_read_axis_3axis(UNUSED(void *priv), int axis) { @@ -257,6 +292,42 @@ const joystick_if_t joystick_2axis_2button = { .pov_names = { NULL } }; +const joystick_if_t joystick_2button_gamepad = { + .name = "2-button gamepad(s)", + .internal_name = "2button_gamepad", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 2, + .pov_count = 0, + .max_joysticks = 2, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "Button 1", "Button 2" }, + .pov_names = { NULL } +}; + +const joystick_if_t joystick_2button_flight_yoke = { + .name = "2-button flight yoke", + .internal_name = "2button_flight_yoke", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 2, + .pov_count = 0, + .max_joysticks = 2, + .axis_names = { "Roll axis", "Pitch axis" }, + .button_names = { "Trigger", "Button 2" }, + .pov_names = { NULL } +}; + const joystick_if_t joystick_2axis_4button = { .name = "2-axis, 4-button joystick", .internal_name = "2axis_4button", @@ -275,6 +346,42 @@ const joystick_if_t joystick_2axis_4button = { .pov_names = { NULL } }; +const joystick_if_t joystick_4button_gamepad = { + .name = "4-button gamepad", + .internal_name = "4button_gamepad", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_4button, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 4, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { NULL } +}; + +const joystick_if_t joystick_4button_flight_yoke = { + .name = "4-button flight yoke", + .internal_name = "4button_flight_yoke", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_4button, + .a0_over = joystick_standard_a0_over, + .axis_count = 2, + .button_count = 4, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "Roll axis", "Pitch axis" }, + .button_names = { "Trigger", "Button 2", "Button 3", "Button 4" }, + .pov_names = { NULL } +}; + const joystick_if_t joystick_3axis_2button = { .name = "3-axis, 2-button joystick", .internal_name = "3axis_2button", @@ -293,6 +400,24 @@ const joystick_if_t joystick_3axis_2button = { .pov_names = { NULL } }; +const joystick_if_t joystick_2button_yoke_throttle = { + .name = "2-button flight yoke with throttle", + .internal_name = "2button_yoke_throttle", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_3axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 3, + .button_count = 2, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "Roll axis", "Pitch axis", "Throttle axis" }, + .button_names = { "Trigger", "Button 2" }, + .pov_names = { NULL } +}; + const joystick_if_t joystick_3axis_4button = { .name = "3-axis, 4-button joystick", .internal_name = "3axis_4button", @@ -311,6 +436,42 @@ const joystick_if_t joystick_3axis_4button = { .pov_names = { NULL } }; +const joystick_if_t joystick_4button_yoke_throttle = { + .name = "4-button flight yoke with throttle", + .internal_name = "4button_yoke_throttle", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_3axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 3, + .button_count = 4, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "Roll axis", "Pitch axis", "Throttle axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { NULL } +}; + +const joystick_if_t joystick_win95_steering_wheel = { + .name = "Win95 Steering Wheel (3-axis, 4-button)", + .internal_name = "win95_steering_wheel", + .init = joystick_standard_init, + .close = joystick_standard_close, + .read = joystick_standard_read_4button, + .write = joystick_standard_write, + .read_axis = joystick_standard_read_axis_3axis, + .a0_over = joystick_standard_a0_over, + .axis_count = 3, + .button_count = 4, + .pov_count = 0, + .max_joysticks = 1, + .axis_names = { "Steering axis", "Accelerator axis", "Brake axis" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { NULL } +}; + const joystick_if_t joystick_4axis_4button = { .name = "4-axis, 4-button joystick", .internal_name = "4axis_4button", diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index e572d670b..4494290d6 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -149,13 +149,14 @@ extern int fpu_type; /* (C) fpu type */ extern int fpu_softfloat; /* (C) fpu uses softfloat */ extern int time_sync; /* (C) enable time sync */ extern int hdd_format_type; /* (C) hard disk file format */ -extern int lba_enhancer_enabled; /* (C) enable Vision Systems LBA Enhancer */ extern int confirm_reset; /* (C) enable reset confirmation */ extern int confirm_exit; /* (C) enable exit confirmation */ extern int confirm_save; /* (C) enable save confirmation */ extern int enable_discord; /* (C) enable Discord integration */ +extern int force_10ms; /* (C) force 10ms CPU frame interval */ extern int other_ide_present; /* IDE controllers from non-IDE cards are present */ extern int other_scsi_present; /* SCSI controllers from non-SCSI cards are present */ +extern int is_pcjr; /* The current machine is PCjr. */ extern int hard_reset_pending; extern int fixed_size_x; diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index 7928cdd30..655eea942 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -15,7 +15,7 @@ * * Copyright 2016-2022 Miran Grca. * Copyright 2008-2018 Sarah Walker. - * Copyright 2021 RichardG. + * Copyright 2021 RichardG. * Copyright 2021-2025 Jasmine Iwanek. */ #ifndef EMU_GAMEPORT_H @@ -52,6 +52,26 @@ #define GAMEPORT_8ADDR 0x080000 #define GAMEPORT_SIO 0x1000000 +typedef struct joystick_if_t { + const char *name; + const char *internal_name; + + void *(*init)(void); + void (*close)(void *priv); + uint8_t (*read)(void *priv); + void (*write)(void *priv); + int (*read_axis)(void *priv, int axis); + void (*a0_over)(void *priv); + + int axis_count; + int button_count; + int pov_count; + int max_joysticks; + const char *axis_names[MAX_JOY_AXES]; + const char *button_names[MAX_JOY_BUTTONS]; + const char *pov_names[MAX_JOY_POVS]; +} joystick_if_t; + typedef struct plat_joystick_t { char name[260]; @@ -90,26 +110,6 @@ typedef struct joystick_t { int pov_mapping[MAX_JOY_POVS][2]; } joystick_t; -typedef struct joystick_if_t { - const char *name; - const char *internal_name; - - void *(*init)(void); - void (*close)(void *priv); - uint8_t (*read)(void *priv); - void (*write)(void *priv); - int (*read_axis)(void *priv, int axis); - void (*a0_over)(void *priv); - - int axis_count; - int button_count; - int pov_count; - int max_joysticks; - const char *axis_names[MAX_JOY_AXES]; - const char *button_names[MAX_JOY_BUTTONS]; - const char *pov_names[MAX_JOY_POVS]; -} joystick_if_t; - extern device_t game_ports[GAMEPORT_MAX]; #ifdef __cplusplus @@ -171,9 +171,16 @@ extern void gameport_remap(void *priv, uint16_t address); extern void *gameport_add(const device_t *gameport_type); extern const joystick_if_t joystick_2axis_2button; +extern const joystick_if_t joystick_2button_gamepad; +extern const joystick_if_t joystick_2button_flight_yoke; extern const joystick_if_t joystick_2axis_4button; +extern const joystick_if_t joystick_4button_gamepad; +extern const joystick_if_t joystick_4button_flight_yoke; extern const joystick_if_t joystick_3axis_2button; +extern const joystick_if_t joystick_2button_yoke_throttle; extern const joystick_if_t joystick_3axis_4button; +extern const joystick_if_t joystick_4button_yoke_throttle; +extern const joystick_if_t joystick_win95_steering_wheel; extern const joystick_if_t joystick_4axis_4button; extern const joystick_if_t joystick_2axis_6button; extern const joystick_if_t joystick_2axis_8button; @@ -186,14 +193,6 @@ 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); -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 diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 0a5985370..ca020b4b2 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -112,9 +112,6 @@ 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; - extern void hdc_init(void); extern void hdc_reset(void); diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index c13d70291..b3e4d070b 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -37,6 +37,7 @@ 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_set_fifo_threshold(int port, int threshold); extern void lpt_reset(void); extern void lpt_close(void); extern void lpt_init(void); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 53001b8db..8710fca51 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -483,6 +483,8 @@ extern void mem_remap_top_nomid(int kb); extern void umc_smram_recalc(uint32_t start, int set); +extern void pcjr_waitstates(void *); + extern mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; extern mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index 8dd3bad2d..79325edef 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -42,6 +42,7 @@ #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_MSBPOINT 15 /* Microsoft Serial BallPoint mouse */ #define MOUSE_TYPE_ONBOARD 0x80 /* Mouse is an on-board version of one of the above. */ @@ -71,6 +72,7 @@ extern const device_t mouse_genibus_device; 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_msserial_ballpoint_device; extern const device_t mouse_ltserial_device; extern const device_t mouse_ps2_device; # ifdef USE_WACOM diff --git a/src/include/86box/net_dp8390.h b/src/include/86box/net_dp8390.h index 553366808..0b1cc45f5 100644 --- a/src/include/86box/net_dp8390.h +++ b/src/include/86box/net_dp8390.h @@ -41,89 +41,89 @@ typedef struct dp8390_t { /* Command Register - 00h read/write */ struct CR_t { - int stop; /* STP - Software Reset command */ - int start; /* START - start the NIC */ - int tx_packet; /* TXP - initiate packet transmission */ + bool stop; /* STP - Software Reset command */ + bool start; /* START - start the NIC */ + bool tx_packet; /* TXP - initiate packet transmission */ uint8_t rdma_cmd; /* RD0,RD1,RD2 - Remote DMA command */ uint8_t pgsel; /* PS0,PS1 - Page select */ } CR; /* Interrupt Status Register - 07h read/write */ struct ISR_t { - int pkt_rx; /* PRX - packet received with no errors */ - int pkt_tx; /* PTX - packet txed with no errors */ - int rx_err; /* RXE - packet rxed with 1 or more errors */ - int tx_err; /* TXE - packet txed " " " " " */ - int overwrite; /* OVW - rx buffer resources exhausted */ - int cnt_oflow; /* CNT - network tally counter MSB's set */ - int rdma_done; /* RDC - remote DMA complete */ - int reset; /* RST - reset status */ + bool pkt_rx; /* PRX - packet received with no errors */ + bool pkt_tx; /* PTX - packet txed with no errors */ + bool rx_err; /* RXE - packet rxed with 1 or more errors */ + bool tx_err; /* TXE - packet txed " " " " " */ + bool overwrite; /* OVW - rx buffer resources exhausted */ + bool cnt_oflow; /* CNT - network tally counter MSB's set */ + bool rdma_done; /* RDC - remote DMA complete */ + bool reset; /* RST - reset status */ } ISR; /* Interrupt Mask Register - 0fh write */ struct IMR_t { - int rx_inte; /* PRXE - packet rx interrupt enable */ - int tx_inte; /* PTXE - packet tx interrput enable */ - int rxerr_inte; /* RXEE - rx error interrupt enable */ - int txerr_inte; /* TXEE - tx error interrupt enable */ - int overw_inte; /* OVWE - overwrite warn int enable */ - int cofl_inte; /* CNTE - counter o'flow int enable */ - int rdma_inte; /* RDCE - remote DMA complete int enable */ - int reserved; /* D7 - reserved */ + bool rx_inte; /* PRXE - packet rx interrupt enable */ + bool tx_inte; /* PTXE - packet tx interrput enable */ + bool rxerr_inte; /* RXEE - rx error interrupt enable */ + bool txerr_inte; /* TXEE - tx error interrupt enable */ + bool overw_inte; /* OVWE - overwrite warn int enable */ + bool cofl_inte; /* CNTE - counter o'flow int enable */ + bool rdma_inte; /* RDCE - remote DMA complete int enable */ + bool reserved; /* D7 - reserved */ } IMR; /* Data Configuration Register - 0eh write */ struct DCR_t { - int wdsize; /* WTS - 8/16-bit select */ - int endian; /* BOS - byte-order select */ - int longaddr; /* LAS - long-address select */ - int loop; /* LS - loopback select */ - int auto_rx; /* AR - auto-remove rx pkts with remote DMA */ + bool wdsize; /* WTS - 8/16-bit select */ + bool endian; /* BOS - byte-order select */ + bool longaddr; /* LAS - long-address select */ + bool loop; /* LS - loopback select */ + bool auto_rx; /* AR - auto-remove rx pkts with remote DMA */ uint8_t fifo_size; /* FT0,FT1 - fifo threshold */ } DCR; /* Transmit Configuration Register - 0dh write */ struct TCR_t { - int crc_disable; /* CRC - inhibit tx CRC */ + bool crc_disable; /* CRC - inhibit tx CRC */ uint8_t loop_cntl; /* LB0,LB1 - loopback control */ - int ext_stoptx; /* ATD - allow tx disable by external mcast */ - int coll_prio; /* OFST - backoff algorithm select */ + bool ext_stoptx; /* ATD - allow tx disable by external mcast */ + bool coll_prio; /* OFST - backoff algorithm select */ uint8_t reserved; /* D5,D6,D7 - reserved */ } TCR; /* Transmit Status Register - 04h read */ struct TSR_t { - int tx_ok; /* PTX - tx complete without error */ - int reserved; /* D1 - reserved */ - int collided; /* COL - tx collided >= 1 times */ - int aborted; /* ABT - aborted due to excessive collisions */ - int no_carrier; /* CRS - carrier-sense lost */ - int fifo_ur; /* FU - FIFO underrun */ - int cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ - int ow_coll; /* OWC - out-of-window collision */ + bool tx_ok; /* PTX - tx complete without error */ + bool reserved; /* D1 - reserved */ + bool collided; /* COL - tx collided >= 1 times */ + bool aborted; /* ABT - aborted due to excessive collisions */ + bool no_carrier; /* CRS - carrier-sense lost */ + bool fifo_ur; /* FU - FIFO underrun */ + bool cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ + bool ow_coll; /* OWC - out-of-window collision */ } TSR; /* Receive Configuration Register - 0ch write */ struct RCR_t { - int errors_ok; /* SEP - accept pkts with rx errors */ - int runts_ok; /* AR - accept < 64-byte runts */ - int broadcast; /* AB - accept eth broadcast address */ - int multicast; /* AM - check mcast hash array */ - int promisc; /* PRO - accept all packets */ - int monitor; /* MON - check pkts, but don't rx */ + bool errors_ok; /* SEP - accept pkts with rx errors */ + bool runts_ok; /* AR - accept < 64-byte runts */ + bool broadcast; /* AB - accept eth broadcast address */ + bool multicast; /* AM - check mcast hash array */ + bool promisc; /* PRO - accept all packets */ + bool monitor; /* MON - check pkts, but don't rx */ uint8_t reserved; /* D6,D7 - reserved */ } RCR; /* Receive Status Register - 0ch read */ struct RSR_t { - int rx_ok; /* PRX - rx complete without error */ - int bad_crc; /* CRC - Bad CRC detected */ - int bad_falign; /* FAE - frame alignment error */ - int fifo_or; /* FO - FIFO overrun */ - int rx_missed; /* MPA - missed packet error */ - int rx_mbit; /* PHY - unicast or mcast/bcast address match */ - int rx_disabled; /* DIS - set when in monitor mode */ - int deferred; /* DFR - collision active */ + bool rx_ok; /* PRX - rx complete without error */ + bool bad_crc; /* CRC - Bad CRC detected */ + bool bad_falign; /* FAE - frame alignment error */ + bool fifo_or; /* FO - FIFO overrun */ + bool rx_missed; /* MPA - missed packet error */ + bool rx_mbit; /* PHY - unicast or mcast/bcast address match */ + bool rx_disabled; /* DIS - set when in monitor mode */ + bool deferred; /* DFR - collision active */ } RSR; uint16_t local_dma; /* 01,02h read ; current local DMA addr */ diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index e72c7af40..8a4867a96 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -19,6 +19,9 @@ #include <86box/rom.h> +#define INT_START_BLKNK_ENAB (1 << 0) +#define INT_MASK 0xf + typedef struct xga_hwcursor_t { int ena; int x; @@ -84,13 +87,13 @@ typedef struct xga_t { uint8_t border_color; uint8_t direct_color; uint8_t dma_channel; - uint8_t instance_isa; uint8_t instance_num; - uint8_t ext_mem_addr; uint8_t vga_post; uint8_t addr_test; uint8_t *vram; uint8_t *changedvram; + uint8_t int_ena; + uint8_t int_stat; int16_t hwc_pos_x; int16_t hwc_pos_y; @@ -151,7 +154,8 @@ typedef struct xga_t { int a5_test; int type; int bus; - int busy; + int src_reverse_order; + int dst_reverse_order; uint32_t linear_base; uint32_t linear_size; @@ -205,6 +209,10 @@ typedef struct xga_t { uint16_t dst_map_y; uint16_t pat_map_x; uint16_t pat_map_y; + uint16_t clip_l; + uint16_t clip_r; + uint16_t clip_t; + uint16_t clip_b; int ssv_state; int pat_src; @@ -218,13 +226,13 @@ typedef struct xga_t { int y; int sx; int sy; - int dx; - int dy; int px; int py; int pattern; int command_len; int filling; + int y_len; + int x_len; uint32_t short_stroke; uint32_t color_cmp; @@ -234,6 +242,7 @@ typedef struct xga_t { uint32_t bkgd_color; uint32_t command; uint32_t dir_cmd; + uint32_t pattern_data; uint8_t px_map_format[4]; uint16_t px_map_width[4]; diff --git a/src/include/86box/vid_xga_device.h b/src/include/86box/vid_xga_device.h index e337ef9d3..7a72e76f5 100644 --- a/src/include/86box/vid_xga_device.h +++ b/src/include/86box/vid_xga_device.h @@ -20,7 +20,6 @@ #ifdef EMU_DEVICE_H extern const device_t xga_device; -extern const device_t xga_isa_device; extern const device_t inmos_isa_device; #endif #endif /*VIDEO_XGA_DEVICE_H*/ diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index e91b9bcf5..8a1cadbb7 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -180,9 +180,9 @@ static const device_config_t pbl300sx_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "1991", .internal_name = "pbl300sx_1991", .bios_type = BIOS_NORMAL, + { .name = "Phoenix ROM BIOS PLUS 1.10 - Revision 19910723091302", .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, + { .name = "Phoenix ROM BIOS PLUS 1.10 - Revision 19920910", .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 } }, @@ -391,46 +391,6 @@ machine_at_tuliptc7_init(const machine_t *model) return ret; } -int -machine_at_micronics386_init(const machine_t *model) -{ - int ret; - - ret = bios_load_interleaved("roms/machines/micronics386/386-Micronics-09-00021-EVEN.BIN", - "roms/machines/micronics386/386-Micronics-09-00021-ODD.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; -} - -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) { @@ -899,9 +859,9 @@ static const device_config_t dells333sl_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "J01 (Jostens Learning Corporation OEM)", .internal_name = "dells333sl_j01", .bios_type = BIOS_NORMAL, + { .name = "Phoenix ROM BIOS PLUS 1.10 - Revision 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, + { .name = "Phoenix ROM BIOS PLUS 1.10 - Revision 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 } }, diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index eb91f300c..731b1e2bd 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -860,11 +860,11 @@ static const device_config_t pb450_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "PCI 1.0A", .internal_name = "pb450a" /*"pci10a"*/, .bios_type = BIOS_NORMAL, + { .name = "PhoenixBIOS 4.03 - Revision PCI 1.0A", .internal_name = "pb450a_pci10a" /*"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, + { .name = "PhoenixBIOS 4.03 - Revision PNP 1.1A", .internal_name = "pb450a", .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, + { .name = "PhoenixBIOS 4.05 - Revision P4HS20 (by Micro Firmware)", .internal_name = "pb450a_p4hs20", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/pb450/p4hs20.bin", "" } }, { .files_no = 0 } }, @@ -1769,11 +1769,11 @@ static const device_config_t sb486pv_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "AMI 062594 (0108)", .internal_name = "sb486pv", .bios_type = BIOS_NORMAL, + { .name = "AMI WinBIOS (062594) - Revision 0108", .internal_name = "sb486pv_0108", .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, + { .name = "AMI WinBIOS (062594) - Revision 0301", .internal_name = "sb486pv_0301", .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, + { .name = "AMIBIOS 6 (071595) - Revision 1301", .internal_name = "sb486pv", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/sb486pv/amiboot.rom", "" } }, { .files_no = 0 } }, @@ -2296,9 +2296,9 @@ static const device_config_t hot433a_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "AMI", .internal_name = "hot433a", .bios_type = BIOS_NORMAL, + { .name = "AMIBIOS 5 (101094) - Revision 433AUS33", .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, + { .name = "AwardBIOS v4.51PG - Revision 2.5 (by eSupport)", .internal_name = "hot433a_v451pg", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/hot433/2A4X5H21.BIN", "" } }, { .files_no = 0 } }, @@ -2919,3 +2919,45 @@ machine_at_cougar_init(const machine_t *model) return ret; } + +int +machine_at_micronics386_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/micronics386/386-Micronics-09-00021-EVEN.BIN", + "roms/machines/micronics386/386-Micronics-09-00021-ODD.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_init(model); + device_add(&port_92_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + 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); + device_add(&port_92_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 3de3bc871..c101fb95a 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -53,7 +53,7 @@ machine_at_v12p_init(const machine_t *model) return ret; device_context(model->device); - fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 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(); @@ -79,30 +79,28 @@ machine_at_v12p_init(const machine_t *model) static const device_config_t v12p_config[] = { // clang-format off { - .name = "bios_versions", - .description = "BIOS Versions", + .name = "bios", + .description = "BIOS Version", .type = CONFIG_BIOS, - .default_string = "v12p_14", + .default_string = "v12p", .default_int = 0, .file_filter = "", .spinner = { 0 }, /*W1*/ .bios = { - { .name = "Core Version 1.2 Version R1.4", .internal_name = "v12p_14", .bios_type = BIOS_NORMAL, + { .name = "Acer BIOS V1.2 - Revision R1.4", .internal_name = "v12p_r14", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/v12p/v12p_14.bin", "" } }, - { .name = "Core Version 1.2 Version R1.6", .internal_name = "v12p_16", .bios_type = BIOS_NORMAL, + { .name = "Acer BIOS V1.2 - Revision R1.6", .internal_name = "v12p", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/v12p/v12p_16.bin", "" } }, - + { .files_no = 0 } }, }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; - - const device_t v12p_device = { .name = "Acer V12P", - .internal_name = "v12p", + .internal_name = "v12p_device", .flags = 0, .local = 0, .init = NULL, @@ -111,7 +109,7 @@ const device_t v12p_device = { .available = NULL, .speed_changed = NULL, .force_redraw = NULL, - .config = &v12p_config[0] + .config = v12p_config }; void diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index b2d3c46f3..a4bb77a55 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -92,10 +92,10 @@ machine_at_d842_init(const machine_t *model) return ret; device_context(model->device); - fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 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(); - + machine_at_common_init(model); device_add(&ide_pci_2ch_device); @@ -118,37 +118,36 @@ machine_at_d842_init(const machine_t *model) static const device_config_t d842_config[] = { // clang-format off { - .name = "bios_versions", - .description = "BIOS Versions", + .name = "bios", + .description = "BIOS Version", .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, + { .name = "PhoenixBIOS Pentium 1.03 - Revision 1.03.842", .internal_name = "d842_103", .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, + { .name = "PhoenixBIOS Pentium 1.03 - Revision 1.09.842", .internal_name = "d842_109", .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, + { .name = "PhoenixBIOS Pentium 1.03 - Revision 1.10.842", .internal_name = "d842", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98_1.bin", "" } }, + { .name = "PhoenixBIOS 4.04 - Revision 1.05.842", .internal_name = "d842_105", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_mar96.bin", "" } }, + { .name = "PhoenixBIOS 4.04 - Revision 1.06.842", .internal_name = "d842_106", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_apr98.bin", "" } }, + { .name = "PhoenixBIOS 4.04 - Revision 1.07.842", .internal_name = "d842_107", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d842/d842_jun98.BIN", "" } }, + { .files_no = 0 } }, }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; - - const device_t d842_device = { .name = "Siemens-Nixdorf D842", - .internal_name = "d842", + .internal_name = "d842_device", .flags = 0, .local = 0, .init = NULL, @@ -157,7 +156,7 @@ const device_t d842_device = { .available = NULL, .speed_changed = NULL, .force_redraw = NULL, - .config = &d842_config[0] + .config = d842_config }; int @@ -195,10 +194,10 @@ machine_at_p54np4_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_2 | PCI_CAN_SWITCH_TYPE); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - 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(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 07 = Slot 1 */ + pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 06 = Slot 2 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 04 = Slot 4 */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430nx_device); device_add(&sio_zb_device); @@ -237,7 +236,7 @@ machine_at_tek932_init(const machine_t *model) if (bios_only || !ret) return ret; - + machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_2 | PCI_CAN_SWITCH_TYPE); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 7d29a6f3a..0dea19a18 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -624,7 +624,7 @@ machine_at_d943_init(const machine_t *model) return ret; device_context(model->device); - fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios_versions"), 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(); @@ -657,22 +657,23 @@ machine_at_d943_init(const machine_t *model) static const device_config_t d943_config[] = { // clang-format off { - .name = "bios_versions", - .description = "BIOS Versions", + .name = "bios", + .description = "BIOS Version", .type = CONFIG_BIOS, - .default_string = "d943_oct96", + .default_string = "d943", .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, + { .name = "PhoenixBIOS 4.05 - Revision 1.02.943", .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, + { .name = "PhoenixBIOS 4.05 - Revision 1.03.943", .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 = "PhoenixBIOS 4.05 - Revision 1.05.943", .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, + { .name = "PhoenixBIOS 4.05 - Revision 1.06.943", .internal_name = "d943", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/d943/d943_oct97.bin", "" } }, + { .files_no = 0 } }, }, { .name = "", .description = "", .type = CONFIG_END } @@ -683,7 +684,7 @@ static const device_config_t d943_config[] = { const device_t d943_device = { .name = "Siemens-Nixdorf D943", - .internal_name = "d943", + .internal_name = "d943_device", .flags = 0, .local = 0, .init = NULL, @@ -692,7 +693,7 @@ const device_t d943_device = { .available = NULL, .speed_changed = NULL, .force_redraw = NULL, - .config = &d943_config[0] + .config = d943_config }; int @@ -800,11 +801,11 @@ static const device_config_t ap5s_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "04/22/96 1.20 4.50PG", .internal_name = "ap5s_450pg", .bios_type = BIOS_NORMAL, + { .name = "AwardBIOS v4.50PG - Revision R1.20", .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, + { .name = "AwardBIOS v4.51PG - Revision R1.50", .internal_name = "ap5s_r150", .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, + { .name = "AwardBIOS v4.51PG - Revision R1.60", .internal_name = "ap5s", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/ap5s/ap5s160.bin", "" } }, { .files_no = 0 } }, @@ -961,11 +962,11 @@ static const device_config_t c5sbm2_config[] = { .file_filter = "", .spinner = { 0 }, .bios = { - { .name = "4.50GP (07/17/1995)", .internal_name = "5sbm2", .bios_type = BIOS_NORMAL, + { .name = "AwardBIOS v4.50GP - Revision 07/17/1995", .internal_name = "5sbm2_v450gp", .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, + { .name = "AwardBIOS v4.50PG - Revision 03/26/1996", .internal_name = "5sbm2", .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, + { .name = "AwardBIOS v4.51PG - Revision 2.2 (by Unicore Software)", .internal_name = "5sbm2_451pg", .bios_type = BIOS_NORMAL, .files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/5sbm2/2A5ICC3A.BIN", "" } }, { .files_no = 0 } }, diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 30a5e609a..092c00b8f 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -829,6 +829,8 @@ machine_pcjr_init(UNUSED(const machine_t *model)) pcjr = calloc(1, sizeof(pcjr_t)); + is_pcjr = 1; + pic_init_pcjr(); pit_common_init(0, pit_irq0_timer_pcjr, NULL); diff --git a/src/machine/machine.c b/src/machine/machine.c index 6a86b785f..66bffdbd2 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -123,6 +123,8 @@ machine_init_ex(int m) pci_flags = 0x00000000; } + is_pcjr = 0; + /* All good, boot the machine! */ if (machines[m].init) ret = machines[m].init(&machines[m]); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 87dd38786..86b75dc39 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1564,7 +1564,7 @@ const machine_t machines[] = { }, { .name = "[8088] Tandy 1000 SX", - .internal_name = "tandy", + .internal_name = "tandy1000sx", .type = MACHINE_TYPE_8088, .chipset = MACHINE_CHIPSET_PROPRIETARY, .init = machine_tandy1000sx_init, @@ -7440,7 +7440,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2_VLB, + .bus_flags = MACHINE_VLB, .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, diff --git a/src/mem/mem.c b/src/mem/mem.c index fa749002c..a544f333c 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -1840,6 +1840,9 @@ mem_read_ram(uint32_t addr, UNUSED(void *priv)) mem_log("Read B %02X from %08X\n", ram[addr], addr); #endif + if (is_pcjr) + pcjr_waitstates(NULL); + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); @@ -2100,6 +2103,9 @@ mem_write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv)) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write B %02X to %08X\n", val, addr); #endif + if (is_pcjr) + pcjr_waitstates(NULL); + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[addr >> 12]); diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index b35e0d453..0eba8a382 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index 623dec56c..a0e0e7129 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -198,6 +199,11 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val) if (dev->TCR.loop_cntl) { dp8390_rx_common(dev, &dev->mem[((dev->tx_page_start * 256) - dev->mem_start) & dev->mem_wrap], dev->tx_bytes); + + if (dev->IMR.rx_inte && !dev->ISR.pkt_tx && dev->interrupt) + dev->interrupt(dev->priv, 1); + + dev->ISR.pkt_tx = 1; } } else if (val & 0x04) { if (dev->CR.stop || (!dev->CR.start && (dev->flags & DP8390_FLAG_CHECK_CR))) { @@ -220,12 +226,6 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val) if (!(dev->card->link_state & NET_LINK_DOWN)) network_tx(dev->card, &dev->mem[((dev->tx_page_start * 256) - dev->mem_start) & dev->mem_wrap], dev->tx_bytes); - /* some more debug */ -#ifdef ENABLE_DP8390_LOG - if (dev->tx_timer_active) - dp8390_log("DP8390: CR write, tx timer still active\n"); -#endif - dp8390_tx(dev, val); } @@ -247,12 +247,12 @@ dp8390_tx(dp8390_t *dev, UNUSED(uint32_t val)) { dev->CR.tx_packet = 0; dev->TSR.tx_ok = 1; - dev->ISR.pkt_tx = 1; /* Generate an interrupt if not masked */ - if (dev->IMR.tx_inte && dev->interrupt) + if (dev->IMR.tx_inte && !dev->ISR.pkt_tx && dev->interrupt) dev->interrupt(dev->priv, 1); - dev->tx_timer_active = 0; + + dev->ISR.pkt_tx = 1; } /* @@ -960,7 +960,6 @@ dp8390_reset(dp8390_t *dev) memset(&dev->TCR, 0x00, sizeof(dev->TCR)); memset(&dev->TSR, 0x00, sizeof(dev->TSR)); memset(&dev->RSR, 0x00, sizeof(dev->RSR)); - dev->tx_timer_active = 0; dev->local_dma = 0; dev->page_start = 0; dev->page_stop = 0; diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index e45b55b22..4b9ef4a19 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -933,7 +934,7 @@ nic_init(const device_t *info) if (dev->board != NE2K_ETHERNEXT_MC) { dev->base_address = device_get_config_hex16("base"); dev->base_irq = device_get_config_int("irq"); - if ((dev->board == NE2K_NE2000) || (dev->board == NE2K_NE2000_COMPAT) || + if ((dev->board == NE2K_NE2000) || (dev->board == NE2K_NE2000_COMPAT) || (dev->board == NE2K_NE2000_COMPAT_8BIT) ) { dev->bios_addr = device_get_config_hex20("bios_addr"); dev->has_bios = !!dev->bios_addr; @@ -1061,7 +1062,7 @@ nic_init(const device_t *info) break; } - + if (set_oui) { /* See if we have a local MAC address configured. */ mac_oui = device_get_config_mac("mac_oui", -1); @@ -1742,7 +1743,7 @@ const device_t ne2000_compat_device = { const device_t ne2000_compat_8bit_device = { .name = "NE2000 Compatible 8-bit", .internal_name = "ne2k8", - .flags = DEVICE_ISA, + .flags = DEVICE_ISA, .local = NE2K_NE2000_COMPAT_8BIT, .init = nic_init, .close = nic_close, diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index 1ca8d8697..890b221e2 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include diff --git a/src/pit.c b/src/pit.c index a283d1205..b99fed799 100644 --- a/src/pit.c +++ b/src/pit.c @@ -247,7 +247,7 @@ ctr_tick(ctr_t *ctr, void *priv) ctr_decrease_count(ctr); } else ctr->count -= (ctr->newcount ? 1 : 2); - if (ctr->count < 0) { + if (ctr->count == 0) { ctr_set_out(ctr, 0, pit); ctr_load_count(ctr); ctr->state = 3; @@ -266,7 +266,7 @@ ctr_tick(ctr_t *ctr, void *priv) ctr_decrease_count(ctr); } else ctr->count -= (ctr->newcount ? 3 : 2); - if (ctr->count < 0) { + if (ctr->count == 0) { ctr_set_out(ctr, 1, pit); ctr_load_count(ctr); ctr->state = 2; @@ -334,7 +334,7 @@ ctr_set_state_1(ctr_t *ctr) { uint8_t mode = (ctr->m & 0x03); int do_reload = !!ctr->incomplete || (mode == 0) || (ctr->state == 0); - + ctr->incomplete = 0; if (do_reload) @@ -358,8 +358,18 @@ ctr_load(ctr_t *ctr) else ctr_set_state_1(ctr); - if (ctr->load_func != NULL) - ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000); + if (ctr->load_func != NULL) { + uint32_t count = ctr->l ? ctr->l : 0x10000; + if (ctr->bcd) { + uint32_t bcd_count = (((count >> 16) & 0xf) * 10000) | + (((count >> 12) & 0xf) * 1000 ) | + (((count >> 8 ) & 0xf) * 100 ) | + (((count >> 4 ) & 0xf) * 10 ) | + (count & 0xf); + ctr->load_func(ctr->m, bcd_count); + } else + ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000); + } pit_log("Counter loaded, state = %i, gate = %i, latch = %i\n", ctr->state, ctr->gate, ctr->latch); } @@ -540,7 +550,8 @@ pit_write(uint16_t addr, uint8_t val, void *priv) ctr_t *ctr; if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { - pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); + pit_log("[%04X:%08X] pit_write(%04X, %02X, %016" PRIX64 ")\n", + CS, cpu_state.pc, addr, val, (uint64_t) (uintptr_t) priv); } switch (addr & 3) { @@ -788,7 +799,8 @@ pit_read(uint16_t addr, void *priv) } if ((dev->flags & (PIT_8254 | PIT_EXT_IO))) { - pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + pit_log("[%04X:%08X] pit_read(%04X, %016" PRIX64 ") = %02X\n", + CS, cpu_state.pc, addr, (uint64_t) (uintptr_t) priv, ret); } return ret; diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 41c81e696..1855df380 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1906,6 +1906,13 @@ strobe(uint8_t old, uint8_t val, void *priv) /* Process incoming character. */ handle_char(dev, dev->data); + if (timer_is_enabled(&dev->timeout_timer)) { + timer_disable(&dev->timeout_timer); +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + } /* ACK it, will be read on next READ STATUS. */ dev->ack = 1; timer_set_delay_u64(&dev->pulse_timer, ISACONST); @@ -1940,6 +1947,13 @@ write_ctrl(uint8_t val, void *priv) /* Process incoming character. */ handle_char(dev, dev->data); + if (timer_is_enabled(&dev->timeout_timer)) { + timer_disable(&dev->timeout_timer); +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + } /* ACK it, will be read on next READ STATUS. */ dev->ack = 1; timer_set_delay_u64(&dev->pulse_timer, ISACONST); diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 904ff34ad..b8f3b20b9 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -34,6 +34,7 @@ #include <86box/plat_dynld.h> #include <86box/ui.h> #include <86box/prt_devs.h> +#include "cpu.h" #ifdef _WIN32 # define GSDLLAPI __stdcall @@ -341,6 +342,14 @@ ps_strobe(uint8_t old, uint8_t val, void *priv) if (!(val & 0x01) && (old & 0x01)) { process_data(dev); + if (timer_is_enabled(&dev->timeout_timer)) { + timer_disable(&dev->timeout_timer); +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + } + dev->ack = true; timer_set_delay_u64(&dev->pulse_timer, ISACONST); @@ -371,6 +380,14 @@ ps_write_ctrl(uint8_t val, void *priv) if (!(val & 0x01) && (dev->ctrl & 0x01)) { process_data(dev); + if (timer_is_enabled(&dev->timeout_timer)) { + timer_disable(&dev->timeout_timer); +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + } + dev->ack = true; timer_set_delay_u64(&dev->pulse_timer, ISACONST); diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index 7604d023e..3acccf830 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -63,6 +63,7 @@ #include <86box/lpt.h> #include <86box/printer.h> #include <86box/prt_devs.h> +#include "cpu.h" #define FULL_PAGE 1 /* set if no top/bot margins */ @@ -391,6 +392,14 @@ strobe(uint8_t old, uint8_t val, void *priv) /* Process incoming character. */ handle_char(dev); + if (timer_is_enabled(&dev->timeout_timer)) { + timer_disable(&dev->timeout_timer); +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + } + /* ACK it, will be read on next READ STATUS. */ dev->ack = 1; @@ -429,6 +438,14 @@ write_ctrl(uint8_t val, void *priv) /* ACK it, will be read on next READ STATUS. */ dev->ack = 1; + if (timer_is_enabled(&dev->timeout_timer)) { + timer_disable(&dev->timeout_timer); +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + } + timer_set_delay_u64(&dev->pulse_timer, ISACONST); timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); } diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 076d5cc42..c71273af8 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -455,6 +455,7 @@ endif() if (UNIX AND NOT APPLE AND NOT HAIKU) target_sources(ui PRIVATE x11_util.c) + target_link_libraries(plat PRIVATE ${CMAKE_DL_LIBS}) find_package(X11 REQUIRED) target_link_libraries(ui PRIVATE X11::X11 X11::Xi) diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 70e6d7b29..56ef18b15 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -147,6 +147,9 @@ msgstr "&Cor RGB" msgid "&RGB Grayscale" msgstr "Tons de cinza &RGB" +msgid "Generic RGBI color monitor" +msgstr "Monitor colorido RGBI genérico" + msgid "&Amber monitor" msgstr "Monitor &âmbar" @@ -384,6 +387,15 @@ msgstr "Ativar (UTC)" msgid "Dynamic Recompiler" msgstr "Recompilador dinâmico" +msgid "CPU frame size" +msgstr "Tamanho de quadro do CPU" + +msgid "Larger frames (less smooth)" +msgstr "Quadros largos (menos suave)" + +msgid "Smaller frames (smoother)" +msgstr "Quadros menores (mais suave)" + msgid "Video:" msgstr "Vídeo:" @@ -600,6 +612,9 @@ msgstr "RTC ISA:" msgid "ISA Memory Expansion" msgstr "Expansão de memória ISA" +msgid "ISA ROM Cards" +msgstr "Placas ROM ISA" + msgid "Card 1:" msgstr "Placa 1:" @@ -612,6 +627,27 @@ msgstr "Placa 3:" msgid "Card 4:" msgstr "Placa 4:" +msgid "Board 1" +msgstr "Placa 1" + +msgid "Board 2" +msgstr "Placa 2" + +msgid "Board 3" +msgstr "Placa 3" + +msgid "Board 4" +msgstr "Placa 4" + +msgid "Generic ISA ROM Board" +msgstr "Placa ROM ISA Genérica" + +msgid "Generic Dual ISA ROM Board" +msgstr "Placa Dual ROM ISA Genérica" + +msgid "Generic Quad ISA ROM Board" +msgstr "Placa Quad ROM ISA Genérica" + msgid "ISABugger device" msgstr "Dispositivo ISABugger" @@ -777,12 +813,39 @@ msgstr "Joystick padrão de 4 eixos, 4 botões" msgid "CH Flightstick Pro" msgstr "CH Flightstick Pro" +msgid "CH Flightstick Pro + CH Pedals" +msgstr "CH Flightstick Pro + CH Pedais" + msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" msgid "Thrustmaster Flight Control System" msgstr "Sistema de Controle de Voo Thrustmaster" +msgid "Thrustmaster FCS + Rudder Control System" +msgstr "Thrustmaster SCV + Sistema de Controle de Leme" + +msgid "2-button gamepad(s)" +msgstr "Gamepad(s) de 2 botões" + +msgid "2-button flight yoke" +msgstr "Manche de voo de 2 botões" + +msgid "4-button gamepad" +msgstr "Gamepad de 4 botões" + +msgid "4-button flight yoke" +msgstr "Manche de voo de 4 botões" + +msgid "2-button flight yoke with throttle" +msgstr "Manche de voo de 2 botões com acelerador" + +msgid "4-button flight yoke with throttle" +msgstr "Manche de voo de 4 botões com acelerador" + +msgid "Win95 Steering Wheel (3-axis, 4-button)" +msgstr "Volante Win95 (3 eixos, 4 botões)" + msgid "None" msgstr "Nenhum" @@ -841,7 +904,7 @@ msgid "About 86Box" msgstr "Sobre o 86Box" msgid "86Box v" -msgstr "86Box versão" +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, 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." @@ -1377,6 +1440,9 @@ msgstr "Mouse de barramento Microsoft (InPort)" msgid "Mouse Systems Serial Mouse" msgstr "Mouse serial Mouse Systems" +msgid "Mouse Systems Bus Mouse" +msgstr "Mouse de barramento Mouse Systems" + msgid "Microsoft Serial Mouse" msgstr "Mouse serial Microsoft" @@ -1413,12 +1479,54 @@ msgstr "Sistema MIDI" msgid "MIDI Input Device" msgstr "Dispositivo de entrada MIDI" +msgid "BIOS file" +msgstr "Arquivo do BIOS" + +msgid "BIOS file (ROM #1)" +msgstr "Arquivo do BIOS (ROM #1)" + +msgid "BIOS file (ROM #2)" +msgstr "Arquivo do BIOS (ROM #2)" + +msgid "BIOS file (ROM #3)" +msgstr "Arquivo do BIOS (ROM #3)" + +msgid "BIOS file (ROM #4)" +msgstr "Arquivo do BIOS (ROM #4)" + msgid "BIOS Address" msgstr "Endereço do BIOS" +msgid "BIOS address (ROM #1)" +msgstr "Endereço do BIOS (ROM #1)" + +msgid "BIOS address (ROM #2)" +msgstr "Endereço do BIOS (ROM #2)" + +msgid "BIOS address (ROM #3)" +msgstr "Endereço do BIOS (ROM #3)" + +msgid "BIOS address (ROM #4)" +msgstr "Endereço do BIOS (ROM #4)" + msgid "Enable BIOS extension ROM Writes" msgstr "Habilitar gravações na ROM de extensão do BIOS" +msgid "Enable BIOS extension ROM Writes (ROM #1)" +msgstr "Habilitar gravações na ROM de extensão do BIOS (ROM #1)" + +msgid "Enable BIOS extension ROM Writes (ROM #2)" +msgstr "Habilitar gravações na ROM de extensão do BIOS (ROM #2)" + +msgid "Enable BIOS extension ROM Writes (ROM #3)" +msgstr "Habilitar gravações na ROM de extensão do BIOS (ROM #3)" + +msgid "Enable BIOS extension ROM Writes (ROM #4)" +msgstr "Habilitar gravações na ROM de extensão do BIOS (ROM #4)" + +msgid "Linear framebuffer base" +msgstr "Base do framebuffer linear" + msgid "Address" msgstr "Endereço" @@ -1428,6 +1536,21 @@ msgstr "IRQ" msgid "BIOS Revision" msgstr "Revisão do BIOS" +msgid "BIOS Version" +msgstr "Versão do BIOS" + +msgid "BIOS Versions" +msgstr "Versões de BIOS" + +msgid "BIOS Language" +msgstr "Idioma do BIOS" + +msgid "IBM 5161 Expansion Unit" +msgstr "Unidade de Expansão IBM 5161" + +msgid "IBM Cassette Basic" +msgstr "Cassete BASIC IBM" + msgid "Translate 26 -> 17" msgstr "Traduzir 26 -> 17" @@ -1443,6 +1566,18 @@ msgstr "Inverter cores" msgid "BIOS size" msgstr "Tamanho do BIOS" +msgid "BIOS size (ROM #1)" +msgstr "Tamanho do BIOS (ROM #1)" + +msgid "BIOS size (ROM #2)" +msgstr "Tamanho do BIOS (ROM #2)" + +msgid "BIOS size (ROM #3)" +msgstr "Tamanho do BIOS (ROM #3)" + +msgid "BIOS size (ROM #4)" +msgstr "Tamanho do BIOS (ROM #4)" + msgid "Map C0000-C7FFF as UMB" msgstr "Mapear C0000-C7FFF como UMB" @@ -1518,6 +1653,9 @@ msgstr "Nível de reverberação" msgid "Interpolation Method" msgstr "Método de interpolação" +msgid "Dynamic Sample Loading" +msgstr "Carregamento dinâmico de amostra" + msgid "Reverb Output Gain" msgstr "Ganho da saída da reverberação" @@ -1605,6 +1743,12 @@ msgstr "DMA baixo" msgid "Enable Game port" msgstr "Ativar a porta do jogo" +msgid "SID Model" +msgstr "Modelo do SID" + +msgid "SID Filter Strength" +msgstr "Força do Filtro SID" + msgid "Surround module" msgstr "Módulo surround" @@ -1617,6 +1761,9 @@ msgstr "Aumentar a interrupção do CODEC na configuração do CODEC (necessári msgid "SB Address" msgstr "Endereço do SB" +msgid "Use EEPROM setting" +msgstr "Usar configuração da EEPROM" + msgid "WSS IRQ" msgstr "WSS IRQ" @@ -1701,6 +1848,9 @@ msgstr "Tipo de RAMDAC" msgid "Blend" msgstr "Mistura" +msgid "Font" +msgstr "Fonte" + msgid "Bilinear filtering" msgstr "Filtragem bilinear" @@ -1746,6 +1896,33 @@ msgstr "Velocidade de transferência" msgid "EMS mode" msgstr "Modo EMS" +msgid "EMS Address" +msgstr "Endereço EMS" + +msgid "EMS 1 Address" +msgstr "Endereço EMS 1" + +msgid "EMS 2 Address" +msgstr "Endereço EMS 2" + +msgid "EMS Memory Size" +msgstr "Tamanho de Memória EMS" + +msgid "EMS 1 Memory Size" +msgstr "Tamanho de Memória EMS 1" + +msgid "EMS 2 Memory Size" +msgstr "Tamanho de Memória EMS 2" + +msgid "Enable EMS" +msgstr "Habilitar EMS" + +msgid "Enable EMS 1" +msgstr "Habilitar EMS 1" + +msgid "Enable EMS 2" +msgstr "Habilitar EMS 2" + msgid "Address for > 2 MB" msgstr "Endereço para > 2 MB" @@ -1902,6 +2079,15 @@ msgstr "Interpolação sRGB" msgid "Linear interpolation" msgstr "Interpolação linear" +msgid "Has secondary 8x8 character set" +msgstr "Tem conjunto secundário de caracteres 8x8" + +msgid "Has Quadcolor II daughter board" +msgstr "Tem placa filha Quadcolor II" + +msgid "Alternate monochrome contrast" +msgstr "Contraste monocromático alternativo" + msgid "128 KB" msgstr "128 KB" @@ -1935,6 +2121,9 @@ msgstr "Âmbar" msgid "Gray" msgstr "Cinza" +msgid "Grayscale" +msgstr "Escala de cinza" + msgid "Color" msgstr "Colorido" @@ -1950,6 +2139,12 @@ msgstr "Outros idiomas" msgid "Bochs latest" msgstr "Bochs mais recente" +msgid "Apply overscan deltas" +msgstr "Aplicar deltas de overscan" + +msgid "Mono Interlaced" +msgstr "Monocromático entrelaçado" + msgid "Mono Non-Interlaced" msgstr "Monocromático não entrelaçado" @@ -2076,6 +2271,12 @@ 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" @@ -2189,3 +2390,15 @@ msgstr "Alternar pausa" msgid "Toggle mute" msgstr "Alternar mudo" + +msgid "Text files" +msgstr "Arquivos de texto" + +msgid "ROM files (*.bin *.rom)|*.bin,*.rom" +msgstr "Arquivos de ROM (*.bin *.rom)|*.bin,*.rom" + +msgid "ROM files" +msgstr "Arquivos de ROM" + +msgid "SoundFont files" +msgstr "Arquivos SoundFont" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index b721d6f29..fe961cc60 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -390,6 +390,15 @@ msgstr "Включено (UTC)" msgid "Dynamic Recompiler" msgstr "Динамический рекомпилятор" +msgid "CPU frame size" +msgstr "Размер кадра ЦП" + +msgid "Larger frames (less smooth)" +msgstr "Большие кадры (менее плавные)" + +msgid "Smaller frames (smoother)" +msgstr "Меньшие кадры (более плавные)" + msgid "Video:" msgstr "Видеокарта 1:" @@ -765,9 +774,21 @@ msgstr "Неверное устройство PCap" msgid "2-axis, 2-button joystick(s)" msgstr "2-осевой, 2-кнопочный джойстик" +msgid "2-button gamepad(s)" +msgstr "2-кнопочный геймпад" + +msgid "2-button flight yoke" +msgstr "2-кнопочный flight yoke" + msgid "2-axis, 4-button joystick" msgstr "2-осевой, 4-кнопочный джойстик" +msgid "4-button gamepad" +msgstr "4-кнопочный геймпад" + +msgid "4-button flight yoke" +msgstr "4-кнопочный flight yoke" + msgid "2-axis, 6-button joystick" msgstr "2-осевой, 6-кнопочный джойстик" @@ -777,21 +798,36 @@ msgstr "2-осевой, 8-кнопочный джойстик" msgid "3-axis, 2-button joystick" msgstr "3-осевой, 2-кнопочный джойстик" +msgid "2-button flight yoke with throttle" +msgstr "2-кнопочный flight yoke с дросселем" + msgid "3-axis, 4-button joystick" msgstr "3-осевой, 4-кнопочный джойстик" +msgid "Win95 Steering Wheel (3-axis, 4-button)" +msgstr "Руль Win95 (3-осевой, 4-кнопочный)" + +msgid "4-button flight yoke with throttle" +msgstr "4-кнопочный flight yoke с дросселем" + msgid "4-axis, 4-button joystick" msgstr "4-осевой, 4-кнопочный джойстик" msgid "CH Flightstick Pro" msgstr "CH Flightstick Pro" +msgid "CH Flightstick Pro + CH Pedals" +msgstr "CH Flightstick Pro + CH Педали" + msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" msgid "Thrustmaster Flight Control System" msgstr "Система управления полётом Thrustmaster" +msgid "Thrustmaster FCS + Rudder Control System" +msgstr "Thrustmaster FCS + Система управления рулем" + msgid "None" msgstr "Нет" @@ -1386,6 +1422,9 @@ msgstr "Bus-мышь Microsoft (InPort)" msgid "Mouse Systems Serial Mouse" msgstr "COM-мышь Mouse Systems" +msgid "Mouse Systems Bus Mouse" +msgstr "Bus-мышь Mouse Systems" + msgid "Microsoft Serial Mouse" msgstr "COM-мышь Microsoft" @@ -1686,6 +1725,12 @@ msgstr "Низкий DMA" msgid "Enable Game port" msgstr "Включить игровой порт" +msgid "SID Model" +msgstr "Модель SID" + +msgid "SID Filter Strength" +msgstr "Сила фильтра SID" + msgid "Surround module" msgstr "Модуль объёмного звучания" @@ -1788,6 +1833,18 @@ msgstr "Смесь" msgid "Font" msgstr "Шрифт" +msgid "Has secondary 8x8 character set" +msgstr "Вторичный набор символов 8x8" + +msgid "Has Quadcolor II daughter board" +msgstr "Дочерняя плата Quadcolor II" + +msgid "Alternate monochrome contrast" +msgstr "Альтернативный монохромный контраст" + +msgid "Video chroma-keying" +msgstr "Видео хромакеинг" + msgid "Bilinear filtering" msgstr "Билинейная фильтрация" @@ -2154,6 +2211,9 @@ msgstr "Скорость передачи данных через канал" msgid "Named Pipe (Server)" msgstr "Именованный пайп (Сервер)" +msgid "Named Pipe (Client)" +msgstr "Именованный пайп (Клиент)" + msgid "Host Serial Passthrough" msgstr "Последовательный порт хоста" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 73d46a007..d2a0bc84b 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -16,7 +16,7 @@ msgid "&Right CTRL is left ALT" msgstr "&Sağ CTRL tuşunu sol ALT tuşu olarak ayarla" msgid "&Hard Reset..." -msgstr "Yeniden başlamaya &zorla" +msgstr "Yeniden başlamaya &zorla..." msgid "&Ctrl+Alt+Del" msgstr "&Ctrl+Alt+Del" @@ -28,7 +28,7 @@ msgid "&Pause" msgstr "&Duraklat" msgid "E&xit..." -msgstr "&Çıkış..." +msgstr "&Çıkış yap..." msgid "&View" msgstr "&Görünüm" @@ -40,22 +40,22 @@ msgid "Hide &toolbar" msgstr "Araç &çubuğunu gizle" msgid "&Resizeable window" -msgstr "&Yeniden boyutlandırılabilir pencere" +msgstr "&Boyutlandırılabilir pencere" msgid "R&emember size && position" -msgstr "&Pencere boyut ve pozisyonunu hatırla" +msgstr "&Pencere boyut ve pozisyonunu kaydet" msgid "Re&nderer" -msgstr "&İşleyici" +msgstr "Derley&ici" msgid "&Qt (Software)" -msgstr "&Qt (Yazılım)" +msgstr "&Qt (Yazılım bazlı)" msgid "Qt (&OpenGL)" -msgstr "Qt (&OpenGL)" +msgstr "Qt (&OpenGL bazlı)" msgid "Open&GL (3.0 Core)" -msgstr "OpenG&L (3.0 bazlı)" +msgstr "OpenG&L (Sürüm 3.0)" msgid "&VNC" msgstr "&VNC" @@ -67,7 +67,7 @@ msgid "F&orce 4:3 display ratio" msgstr "4:3 görüntü oranına &zorla" msgid "&Window scale factor" -msgstr "Pencere &ölçek çarpanı" +msgstr "Pencere &boyutu ölçeği" msgid "&0.5x" msgstr "&0.5x" @@ -109,7 +109,7 @@ msgid "&Linear" msgstr "Doğ&rusal" msgid "Hi&DPI scaling" -msgstr "HiDPI ölçekle&mesi" +msgstr "HiDPI boyutlandır&ması" msgid "&Fullscreen" msgstr "Tam ekran" @@ -118,13 +118,13 @@ msgid "Fullscreen &stretch mode" msgstr "Tam e&kran germe modu" msgid "&Full screen stretch" -msgstr "&Tam ekrana ger" +msgstr "Ekranın &tamamına ger" msgid "&4:3" msgstr "&4:3" msgid "&Square pixels (Keep ratio)" -msgstr "&Kare piksel (ölçeği koru)" +msgstr "&Kare piksel (ölçeği değiştirme)" msgid "&Integer scale" msgstr "Tam &sayı ölçeklemesi" @@ -142,22 +142,22 @@ msgid "VGA screen &type" msgstr "VGA ekran &tipi" msgid "RGB &Color" -msgstr "RGB (&renkli)" +msgstr "RGB (&Çok renkli)" msgid "&RGB Grayscale" -msgstr "RGB (&gri tonlama)" +msgstr "RGB (&Gri tonlu)" msgid "&Amber monitor" -msgstr "&Kehribar renkli monitör" +msgstr "&Kehribar monitör" msgid "&Green monitor" -msgstr "&Yeşil renkli monitör" +msgstr "&Yeşil monitör" msgid "&White monitor" -msgstr "&Beyaz renkli monitör" +msgstr "&Beyaz monitör" msgid "Grayscale &conversion type" -msgstr "&Gri tonlama dönüştürme türü" +msgstr "&Gri tonlu dönüşüm türü" msgid "BT&601 (NTSC/PAL)" msgstr "BT&601 (NTSC/PAL)" @@ -172,7 +172,7 @@ msgid "CGA/PCjr/Tandy/E&GA/(S)VGA overscan" msgstr "CGA/PCjr/Tandy/E&GA/(S)VGA aşırı taraması" msgid "Change contrast for &monochrome display" -msgstr "Gri to&nlamalı görüntü için kontrastı değiştir" +msgstr "Gri to&nlu görüntü için kontrastı değiştir" msgid "&Media" msgstr "&Medya" @@ -199,7 +199,7 @@ msgid "S&ound" msgstr "&Ses" msgid "Sound &gain..." -msgstr "&Ses düzeyi artışı..." +msgstr "&Sesi artır..." msgid "Begin trace" msgstr "İzlemeyi başlat" @@ -211,7 +211,7 @@ msgid "&Help" msgstr "&Yardım" msgid "&Documentation..." -msgstr "&Dökümanlar..." +msgstr "&Belgeler..." msgid "&About 86Box..." msgstr "&86Box hakkında..." @@ -232,22 +232,22 @@ msgid "&Play" msgstr "&Oynat" msgid "&Rewind to the beginning" -msgstr "&Başlangıca geri sar" +msgstr "&Başa geri sar" msgid "&Fast forward to the end" -msgstr "Sona doğru &ileri sar" +msgstr "Sona &doğru sar" msgid "E&ject" msgstr "&Çıkar" msgid "&Image..." -msgstr "&İmaj..." +msgstr "&İmaj seç..." msgid "E&xport to 86F..." -msgstr "&86F dosyası olarak kaydet..." +msgstr "&86F olarak kaydet..." msgid "&Mute" -msgstr "&Sesi kapat" +msgstr "&Sessize al" msgid "E&mpty" msgstr "İmajı &çıkar" @@ -256,7 +256,7 @@ msgid "Reload previous image" msgstr "Önceki imajı yeniden seç" msgid "&Folder..." -msgstr "&Klasör..." +msgstr "&Klasör seç..." msgid "Target &framerate" msgstr "Hedef &kare hızı oranı" @@ -292,7 +292,7 @@ msgid "Preferences" msgstr "Tercihler" msgid "Sound Gain" -msgstr "Ses düzeyi artışı" +msgstr "Ses Artışı" msgid "New Image" msgstr "Yeni imaj" @@ -301,13 +301,13 @@ msgid "Settings" msgstr "Ayarlar" msgid "Specify Main Window Dimensions" -msgstr "Ana pencere boyutunu belirle" +msgstr "Ana Pencere Boyutunu Belirle" msgid "OK" msgstr "Tamam" msgid "Cancel" -msgstr "İptal" +msgstr "İptal et" msgid "&Default" msgstr "&Varsayılan" @@ -316,7 +316,7 @@ msgid "Language:" msgstr "Dil:" msgid "Gain" -msgstr "Artış" +msgstr "Artış düzeyi" msgid "File name:" msgstr "Dosya adı:" @@ -358,7 +358,7 @@ msgid "Frequency:" msgstr "Saat hızı:" msgid "FPU:" -msgstr "Kayan Nokta Birimi (FPU):" +msgstr "FPU:" msgid "Wait states:" msgstr "Bekleme süreleri:" @@ -367,7 +367,7 @@ msgid "MB" msgstr "MB" msgid "Memory:" -msgstr "Bellek:" +msgstr "Bellek (RAM):" msgid "Time synchronization" msgstr "Zaman senkronizasyonu" @@ -382,58 +382,58 @@ msgid "Enabled (UTC)" msgstr "Etkin (UTC)" msgid "Dynamic Recompiler" -msgstr "Dinamik derleyici" +msgstr "Dinamik Derleyici" msgid "Video:" msgstr "Ekran kartı:" msgid "Video #2:" -msgstr "Ekran kartı 2:" +msgstr "İkincil ekran kartı:" msgid "Voodoo 1 or 2 Graphics" -msgstr "Voodoo 1 veya 2 grafikleri" +msgstr "Voodoo 1 veya 2 Grafikleri" msgid "IBM 8514/A Graphics" -msgstr "IBM 8514/A grafikleri" +msgstr "IBM 8514/A Grafikleri" msgid "XGA Graphics" -msgstr "XGA grafikleri" +msgstr "XGA Grafikleri" msgid "Mouse:" msgstr "Fare:" msgid "Joystick:" -msgstr "Oyun kolu:" +msgstr "Oyun Kolu:" msgid "Joystick 1..." -msgstr "Oyun kolu 1..." +msgstr "1. Oyun Kolu..." msgid "Joystick 2..." -msgstr "Oyun kolu 2..." +msgstr "2. Oyun Kolu..." msgid "Joystick 3..." -msgstr "Oyun kolu 3..." +msgstr "3. Oyun Kolu..." msgid "Joystick 4..." -msgstr "Oyun kolu 4..." +msgstr "4. Oyun Kolu..." msgid "Sound card #1:" -msgstr "Ses kartı 1:" +msgstr "1. Ses Kartı:" msgid "Sound card #2:" -msgstr "Ses kartı 2:" +msgstr "2. Ses Kartı:" msgid "Sound card #3:" -msgstr "Ses kartı 3:" +msgstr "3. Ses Kartı:" msgid "Sound card #4:" -msgstr "Ses kartı 4:" +msgstr "4. Ses Kartı:" msgid "MIDI Out Device:" -msgstr "MIDI çıkış cihazı:" +msgstr "MIDI Çıkış Cihazı:" msgid "MIDI In Device:" -msgstr "MIDI giriş cihazı:" +msgstr "MIDI Giriş Cihazı:" msgid "Standalone MPU-401" msgstr "Bağımsız MPU-401" @@ -451,79 +451,79 @@ msgid "YMFM (faster)" msgstr "YMFM (daha hızlı)" msgid "COM1 Device:" -msgstr "COM1 cihazı:" +msgstr "COM1 Cihazı:" msgid "COM2 Device:" -msgstr "COM2 cihazı:" +msgstr "COM2 Cihazı:" msgid "COM3 Device:" -msgstr "COM3 cihazı:" +msgstr "COM3 Cihazı:" msgid "COM4 Device:" -msgstr "COM4 cihazı:" +msgstr "COM4 Cihazı:" msgid "LPT1 Device:" -msgstr "LPT1 cihazı:" +msgstr "LPT1 Cihazı:" msgid "LPT2 Device:" -msgstr "LPT2 cihazı:" +msgstr "LPT2 Cihazı:" msgid "LPT3 Device:" -msgstr "LPT3 cihazı:" +msgstr "LPT3 Cihazı:" msgid "LPT4 Device:" -msgstr "LPT4 cihazı:" +msgstr "LPT4 Cihazı:" msgid "Serial port 1" -msgstr "Seri port 1" +msgstr "1. Seri Port" msgid "Serial port 2" -msgstr "Seri port 2" +msgstr "2. Seri Port" msgid "Serial port 3" -msgstr "Seri port 3" +msgstr "3. Seri Port" msgid "Serial port 4" -msgstr "Seri port 4" +msgstr "4. Seri Port" msgid "Parallel port 1" -msgstr "Paralel port 1" +msgstr "1. Paralel Port" msgid "Parallel port 2" -msgstr "Paralel port 2" +msgstr "2. Paralel Port" msgid "Parallel port 3" -msgstr "Paralel port 3" +msgstr "3. Paralel Port" msgid "Parallel port 4" -msgstr "Paralel port 4" +msgstr "4. Paralel Port" msgid "HD Controller:" -msgstr "Hard disk kontrolcüsü:" +msgstr "Hard Disk Denetleyicisi:" msgid "FD Controller:" -msgstr "Disket sürücü kontrolcüsü:" +msgstr "Disket Denetleyicisi:" msgid "Tertiary IDE Controller" -msgstr "Üçlü IDE kontrolcüsü" +msgstr "Üçlü IDE Denetleyici" msgid "Quaternary IDE Controller" -msgstr "Dörtlü IDE kontrolcüsü" +msgstr "Dörtlü IDE Denetleyici" msgid "SCSI" msgstr "SCSI" msgid "Controller 1:" -msgstr "Kontrolcü 1:" +msgstr "1. Denetleyici:" msgid "Controller 2:" -msgstr "Kontrolcü 2:" +msgstr "2. Denetleyici:" msgid "Controller 3:" -msgstr "Kontrolcü 3:" +msgstr "3. Denetleyici:" msgid "Controller 4:" -msgstr "Kontrolcü 4:" +msgstr "4. Denetleyici:" msgid "Cassette" msgstr "Kaset" @@ -532,10 +532,10 @@ msgid "Hard disks:" msgstr "Hard diskler:" msgid "&New..." -msgstr "&Yeni..." +msgstr "&Yeni imaj oluştur" msgid "&Existing..." -msgstr "&Var olanı seç..." +msgstr "&İmaj dosyası seç" msgid "&Remove" msgstr "&Kaldır" @@ -568,7 +568,7 @@ msgid "Type:" msgstr "Tür:" msgid "Image Format:" -msgstr "İmaj düzeni:" +msgstr "İmaj Türü:" msgid "Block Size:" msgstr "Blok boyutu:" @@ -577,7 +577,7 @@ msgid "Floppy drives:" msgstr "Disket sürücüleri:" msgid "Turbo timings" -msgstr "Turbo zamanlamaları" +msgstr "Turbo zamanlaması" msgid "Check BPB" msgstr "BPB'yi denetle" @@ -598,7 +598,7 @@ msgid "ISA RTC:" msgstr "ISA RTC:" msgid "ISA Memory Expansion" -msgstr "ISA bellek artırma" +msgstr "ISA Bellek Artırıcı" msgid "Card 1:" msgstr "Kart 1:" @@ -639,8 +639,14 @@ msgstr "ZIP %1 %2 (%3): %4" msgid "ZIP images" msgstr "ZIP imajları" -msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box kullanılabilir hiçbir ROM imajı bulamadı.\n\nLütfen ROM setini indirin ve \"Roms\" klasörüne çıkarın." +msgid "" +"86Box could not find any usable ROM images.\n" +"\n" +"Please download a ROM set and extract it into the \"roms\" directory." +msgstr "" +"86Box kullanılabilir hiçbir ROM dosyası bulamadı.\n" +"\n" +"Lütfen bir ROM seti indirip \"roms\" klasörüne çıkarın." msgid "(empty)" msgstr "(boş)" @@ -667,16 +673,16 @@ msgid "Surface images" msgstr "Yüzey imajları" msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." -msgstr "\"%hs\" makinesi roms/machines klasöründe gerekli ROM imajlarının mevcut olmaması nedeniyle kullanılamıyor. Bundan dolayı kullanılabilen bir makineye geçiş yapılacaktır." +msgstr "\"%hs\" makinesi roms/machines klasöründe gerekli ROM dosyalarının mevcut olmaması nedeniyle kullanılamıyor. Kullanılabilen başka bir makineye geçiş yapılacaktır." 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." +msgstr "\"%hs\" ekran kartı roms/video klasöründe gerekli ROM dosyalarının mevcut olmaması nedeniyle kullanılamıyor. Kullanılabilen başka 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." +msgstr "\"%hs\" ikincil ekran kartı roms/video klasöründe gerekli ROM dosyalarının mevcut olmaması nedeniyle kullanılamıyor. Bu cihaz devre dışı bırakılacaktı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." +msgstr "\"%hs\" cihazı gerekli ROM dosyalarının mevcut olmaması nedeniyle kullanılamıyor. Bu cihaz yok sayılacaktır." msgid "Machine" msgstr "Makine" @@ -685,7 +691,7 @@ msgid "Display" msgstr "Görüntü" msgid "Input devices" -msgstr "Giriş aygıtları" +msgstr "Giriş cihazları" msgid "Sound" msgstr "Ses" @@ -697,7 +703,7 @@ msgid "Ports (COM & LPT)" msgstr "Portlar (COM & LPT)" msgid "Storage controllers" -msgstr "Depolama kontrolcüleri" +msgstr "Depolama denetleyicileri" msgid "Hard disks" msgstr "Hard diskler" @@ -718,7 +724,7 @@ msgid "Press %1 to release mouse" msgstr "Farenin bırakılması için %1 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" +msgstr "Farenin bırakılması için %1 veya tekerlek tuşuna basın" msgid "Bus" msgstr "Veri yolu" @@ -820,19 +826,19 @@ msgid "Welcome to 86Box!" msgstr "86Box'a hoşgeldiniz!" msgid "Internal device" -msgstr "Dahili cihazı" +msgstr "Dahili cihaz" msgid "Exit" -msgstr "Çıkış" +msgstr "Çıkış yap" msgid "No ROMs found" -msgstr "Hiçbir ROM imajı bulunamadı" +msgstr "Hiçbir ROM dosyası bulunamadı" msgid "Do you want to save the settings?" msgstr "Ayarları kaydetmek istediğinizden emin misiniz?" msgid "This will hard reset the emulated machine." -msgstr "Bu işlem makineyi zorla yeniden başlatacak." +msgstr "Bu işlem makineyi yeniden başlamaya zorlayacak." msgid "Save" msgstr "Kaydet" @@ -843,23 +849,49 @@ msgstr "86Box hakkında" 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 "Bir eski bilgisayar emülatörü\n\nYapımcılar: 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 ve diğerleri.\n\nSarah Walker, leilei, JohnElliott, greatpsycho, ve diğerlerinin önceki katkılarıyla birlikte.\n\nGNU Genel Kamu Lisansı versiyon 2 veya sonrası altında yayınlanmıştır. Daha fazla bilgi için LICENSE'ı gözden geçirin." +msgid "" +"An emulator of old computers\n" +"\n" +"Authors: 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" +"\n" +"With previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n" +"\n" +"Released under the GNU General Public License version 2 or later. See LICENSE for more information." +msgstr "" +"Bir eski bilgisayar emülatörü\n" +"\n" +"Yapımcılar: 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 ve diğerleri.\n" +"\n" +"Sarah Walker, leilei, JohnElliott, greatpsycho, ve diğerlerinin önceki katkılarıyla birlikte.\n" +"\n" +"GNU Genel Kamu Lisansı versiyon 2 veya sonrası altında yayınlanmıştır. Daha fazla bilgi için LICENSE kısmını gözden geçirin." msgid "Hardware not available" -msgstr "Donanım mevcut değil" +msgstr "Cihaz mevcut değil" msgid "Make sure %1 is installed and that you are on a libpcap-compatible network connection." msgstr "%1 kurulu olduğundan ve libpcap uyumlu bir internet ağı kullandığınızdan emin olun." msgid "Invalid configuration" -msgstr "Geçersiz konfigürasyon" +msgstr "Geçersiz yapılandırma" -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 PostScript dosyalarının otomatik olarak PDF dosyalarına çevirilmesi için gereklidir.\n\nGenel PostScript yazıcısına gönderilen tüm dökümanlar PostScript (.ps) dosyaları olarak kaydedilecektir." +msgid "" +"%1 is required for automatic conversion of PostScript files to PDF.\n" +"\n" +"Any documents sent to the generic PostScript printer will be saved as PostScript (.ps) files." +msgstr "" +"%1 PostScript dosyalarının otomatik olarak PDF dosyasına çevirilmesi için gereklidir.\n" +"\n" +"Genel PostScript yazıcısına gönderilen tüm dökümanlar PostScript (.ps) dosyası olarak kaydedilecektir." -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 "" +"%1 is required for automatic conversion of PCL files to PDF.\n" +"\n" +"Any 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 dosyasına çevirilmesi için gereklidir.\n" +"\n" +"Genel PostScript yazıcısına gönderilen tüm dökümanlar Printer Command Language (.pcl) dosyası olarak kaydedilecektir." msgid "Don't show this message again" msgstr "Bu mesajı bir daha gösterme" @@ -877,7 +909,7 @@ msgid "CD-ROM images" msgstr "CD-ROM imajları" msgid "%1 Device Configuration" -msgstr "%1 cihaz konfigürasyonu" +msgstr "%1 Cihaz Yapılandırması" msgid "Monitor in sleep mode" msgstr "Monitör uyku modunda" @@ -886,10 +918,20 @@ msgid "GLSL shaders" msgstr "GLSL gölgelendiricileri" msgid "You are loading an unsupported configuration" -msgstr "Desteklenmeyen bir konfigürasyon kullanıyorsunuz" +msgstr "Desteklenmeyen bir yapılandırma kullanıyorsunuz" -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 "Seçtiğiniz makineye uygun işlemci türü filtrelemesi bu emüle edilen makine için devre dışı bırakıldı.\n\nBu normalde makine ile uyumlu olmayan bir işlemci seçmenizi mümkün kılmaktadır. Ancak, bundan dolayı makinenin BIOS'u veya üzerinde kullanılan diğer yazılımlar ile uyumsuzluk sorunları yaşayabilirsiniz.\n\nBu filtrelemenin devre dışı bırakılması resmi olarak desteklenmemektedir ve açtığınız hata raporları geçersiz olarak kapatılabilir." +msgid "" +"CPU type filtering based on selected machine is disabled for this emulated machine.\n" +"\n" +"This 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" +"\n" +"Enabling this setting is not officially supported and any bug reports filed may be closed as invalid." +msgstr "" +"Seçtiğiniz makineyle uygun işlemci filtresi bu yapılandırma için devre dışı bırakıldı.\n" +"\n" +"Bu durum seçili makine ile uyumsuz bir işlemci kullanmanızı mümkün kılmaktadır. Ancak bundan dolayı makinenin BIOS'unda veya çalıştırılan diğer yazılımlarda uyumsuzluk sorunları meydana gelebilir.\n" +"\n" +"İşlemci filtresinin devre dışı bırakılması resmi olarak desteklenmemektedir ve bu esnada açtığınız hata raporları geçersiz sayılabilir." msgid "Continue" msgstr "Devam et" @@ -907,7 +949,7 @@ msgid "Cartridge images" msgstr "Kartuş imajları" msgid "Resume execution" -msgstr "Çalıştırmaya devam et" +msgstr "Çalıştırmayı sürdür" msgid "Pause execution" msgstr "Çalıştırmayı duraklat" @@ -922,13 +964,13 @@ msgid "Hard reset" msgstr "Makineyi yeniden başlat" msgid "ACPI shutdown" -msgstr "ACPI kapanma" +msgstr "Makineyi ACPI kullanarak kapat" msgid "Hard disk (%1)" msgstr "Hard disk (%1)" msgid "MFM/RLL or ESDI CD-ROM drives never existed" -msgstr "MFM/RLL veya ESDI CD-ROM sürücüleri hiçbir zaman var olmamıştır" +msgstr "MFM/RLL veya ESDI CD-ROM sürücüleri hiçbir zaman kullanılmamıştır" msgid "Custom..." msgstr "Diğer..." @@ -937,13 +979,13 @@ msgid "Custom (large)..." msgstr "Diğer (büyük)..." msgid "Add New Hard Disk" -msgstr "Yeni hard disk dosyası oluştur" +msgstr "Yeni Hard Disk İmajı Oluştur" msgid "Add Existing Hard Disk" -msgstr "Var olan bir hard disk dosyası ekle" +msgstr "Var Olan Hard Disk İmajı Ekleme" msgid "HDI disk images cannot be larger than 4 GB." -msgstr "HDI disk imajları 4 GB boyutundan daha büyük olamaz." +msgstr "HDI imajları 4 GB boyutundan daha büyük olamaz." msgid "Disk images cannot be larger than 127 GB." msgstr "Disk imajları 127 GB boyutundan daha büyük olamaz." @@ -958,10 +1000,10 @@ msgid "Unable to write file" msgstr "Dosyanın üzerine yazılamıyor" msgid "HDI or HDX images with a sector size other than 512 are not supported." -msgstr "512 dışında sektör boyutu olan HDI veya HDX imajları desteklenmemektedir." +msgstr "512 dışında sektör boyutu olan HDI ve HDX imajları desteklenmemektedir." msgid "Disk image file already exists" -msgstr "Bu disk imaj dosyası zaten mevcuttur" +msgstr "Bu imaj dosyası zaten mevcuttur" msgid "Please specify a valid file name." msgstr "Lütfen geçerli bir dosya ismi belirleyin." @@ -973,16 +1015,16 @@ msgid "Make sure the file exists and is readable." msgstr "Dosyanın var olduğuna ve okunabildiğine emin olun." msgid "Make sure the file is being saved to a writable directory." -msgstr "Dosyanın yazılabilir bir klasöre kaydedildiğinden emin olun." +msgstr "Dosyanın erişilebilir bir klasöre kaydedildiğinden emin olun." msgid "Disk image too large" msgstr "Disk imajı çok büyük" msgid "Remember to partition and format the newly-created drive." -msgstr "Yeni oluşturulan diskte bölümler oluşturmayı ve formatlamayı unutmayın." +msgstr "Yeni oluşturulan diskte bölümler oluşturmayı ve bu bölümleri biçimlendirmeyi unutmayın." msgid "The selected file will be overwritten. Are you sure you want to use it?" -msgstr "Seçili dosyanın üzerine yazılacaktır. Bunu yapmak istediğinizden emin misiniz?" +msgstr "Seçili dosyanın üzerine yazılacaktır. Bu dosyayı kullanmak istediğinizden emin misiniz?" msgid "Unsupported disk image" msgstr "Desteklenmeyen disk imajı" @@ -1003,13 +1045,13 @@ msgid "HDX image" msgstr "HDX imajı" msgid "Fixed-size VHD" -msgstr "Sabit-boyutlu VHD" +msgstr "Sabit boyutlu VHD" msgid "Dynamic-size VHD" -msgstr "Dinamik-boyutlu VHD" +msgstr "Dinamik boyutlu VHD" msgid "Differencing VHD" -msgstr "Farklandırılan VHD" +msgstr "Farklandıran VHD" msgid "(N/A)" msgstr "(yok)" @@ -1030,7 +1072,7 @@ msgid "Dynamic-size VHD (.vhd)" msgstr "Dinamik boyutlu VHD (.vhd)" msgid "Differencing VHD (.vhd)" -msgstr "Farklandırılan VHD (.vhd)" +msgstr "Farklandıran VHD (.vhd)" msgid "Large blocks (2 MB)" msgstr "Büyük bloklar (2 MB)" @@ -1044,14 +1086,24 @@ msgstr "VHD dosyaları" msgid "Select the parent VHD" msgstr "Ana VHD dosyasını seçin" -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 "Bu, farklandırılmış imaj dosyası oluşturulduktan sonra ana imaj dosyası üzerinde değişiklik yapıldığı anlamına geliyor olabilir.\n\nBu durum ayrıca imaj dosyaları kopyalandığında veya yerleri değiştirildiğinde veya imaj dosyalarını oluşturan programdaki bir hatadan dolayı da olmuş olabilir.\n\nZaman damgalarını düzeltmek ister misiniz?" +msgid "" +"This could mean that the parent image was modified after the differencing image was created.\n" +"\n" +"It can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n" +"\n" +"Do you want to fix the timestamps?" +msgstr "" +"Bu, farklandırmış imaj dosyası oluşturulduktan sonra ana imaj dosyasında bir değişiklik yapıldığı anlamına geliyor olabilir.\n" +"\n" +"Bu durum ayrıca imaj dosyalarının kopyalanmasından, yerlerinin değiştirilmesinden veya dosyaları oluşturan programdaki bir hatadan dolayı da meydana gelmiş olabilir.\n" +"\n" +"Zaman damgalarını düzeltmek ister misiniz?" msgid "Parent and child disk timestamps do not match" msgstr "Ana ve ek disklerin zaman damgaları uyuşmuyor" msgid "Could not fix VHD timestamp." -msgstr "VHD zaman damgası düzeltilemedi." +msgstr "VHD'nin zaman damgası düzeltilemedi." msgid "MFM/RLL" msgstr "MFM/RLL" @@ -1144,16 +1196,16 @@ msgid "Perfect RPM" msgstr "Mükemmel RPM" msgid "1% below perfect RPM" -msgstr "mükemmel RPM değerinin 1% altı" +msgstr "Mükemmel RPM değerinin 1% altı" msgid "1.5% below perfect RPM" -msgstr "mükemmel RPM değerinin 1.5% altı" +msgstr "Mükemmel RPM değerinin 1.5% altı" msgid "2% below perfect RPM" -msgstr "mükemmel RPM değerinin 2% altı" +msgstr "Mükemmel RPM değerinin 2% altı" msgid "(System Default)" -msgstr "(Sistem varsayılanı)" +msgstr "(Sistem Varsayılanı)" msgid "Failed to initialize network driver" msgstr "Ağ sürücüsü başlatılamadı" @@ -1165,7 +1217,7 @@ msgid "Mouse sensitivity:" msgstr "Fare hassasiyeti:" msgid "Select media images from program working directory" -msgstr "Medya görüntülerini programın çalışma dizininden seç" +msgstr "Medya imajlarını programın çalışma dizininden seç" msgid "PIT mode:" msgstr "PIT modu:" @@ -1180,19 +1232,29 @@ msgid "Fast" msgstr "Hızlı" msgid "&Auto-pause on focus loss" -msgstr "Pencere &odağı kaybında otomatik olarak duraklat" +msgstr "Pencereye &odaklanmıyorken duraklat" msgid "WinBox is no longer supported" msgstr "WinBox artık desteklenmemektedir" -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 "WinBox yöneticisinin geliştirilmesi 2022 yılında bakımcı eksikliği nedeniyle durduruldu. Çabalarımızı 86Box'ı daha da iyi hale getirmeye yönlendirdiğimiz için bu yöneticiyi artık desteklememe kararı aldık.\n\nArtık WinBox aracılığıyla güncellemeler sağlanmayacaktır ve onu 86Box'ın yeni sürümleriyle kullanmaya devam etmeniz halinde hatalarla karşılaşabilirsiniz. Bunun yanı sıra WinBox ile ilgili tüm hata raporları geçersiz olarak kapatılacaktır.\n\nKullanabileceğiniz diğer yöneticilerin listesi için 86box.net adresini ziyaret edebilirsiniz." +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" +"\n" +"No 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" +"\n" +"Go to 86box.net for a list of other managers you can use." +msgstr "" +"WinBox yöneticisinin geliştirilmesi geliştirici eksikliği nedeniyle 2022 yılında durduruldu. 86Box'ı daha iyi hale getirmeye odaklanmak amacıyla bu yöneticiyi artık desteklememe kararı aldık.\n" +"\n" +"Artık WinBox aracılığıyla güncellemeler yayınlanmayacaktır ve bu yöneticiyi 86Box'ın yeni sürümleriyle kullanmanız halinde hatalarla karşılaşabilirsiniz. WinBox'ın kullanımıyla ilgili tüm hata raporları geçersiz sayılacaktır.\n" +"\n" +"Kullanabileceğiniz diğer yöneticilerin bir listesi için lütfen 86box.net adresini ziyaret edin." msgid "Generate" msgstr "Oluştur" msgid "Joystick configuration" -msgstr "Oyun kolu yapılandırması" +msgstr "Oyun kolu seçenekleri" msgid "Device" msgstr "Cihaz" @@ -1228,7 +1290,7 @@ msgid "Open screenshots folder..." msgstr "Ekran görüntüsü klasörünü aç..." msgid "Apply fullscreen stretch mode when maximized" -msgstr "Büyütüldüğünde tam ekran genişletme modu uygula" +msgstr "Büyütüldüğünde tam ekran germe modunu uygula" msgid "Cursor/Puck" msgstr "İmleç/Puck" @@ -1237,13 +1299,13 @@ msgid "Pen" msgstr "Kalem" msgid "Host CD/DVD Drive (%1:)" -msgstr "Ana bilgisayar CD/DVD sürücüsü (%1:)" +msgstr "Ana Sistemin CD/DVD Sürücüsü (%1:)" msgid "&Connected" msgstr "&Bağlı" msgid "Clear image history" -msgstr "İmaj geçmişini temizleyin" +msgstr "İmaj geçmişini temizle" msgid "Create..." msgstr "Oluştur..." @@ -1296,17 +1358,27 @@ 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 "\nFalling back to software rendering." -msgstr "\nYazılım işleyicisine geri dönülüyor." +msgid "" +"\n" +"Falling back to software rendering." +msgstr "" +"\n" +"Yazılım derleyicisine geri dönülüyor." 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.

" +msgstr "

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

" msgid "This machine might have been moved or copied." msgstr "Bu makine taşınmış veya kopyalanmış olabilir." -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 "Ağ bağlantısı özelliğinin doğru şekilde çalışmasını sağlamak amacıyla 86Box'ın bu makinenin taşındığını mı yoksa kopyalandığını mı bilmesi gerekmektedir.\n\nEğer bundan emin değilseniz \"Kopyalandı\" seçeneğini seçiniz." +msgid "" +"In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n" +"\n" +"Select \"I Copied It\" if you are not sure." +msgstr "" +"Ağ bağlantısı özelliğinin doğru bir şekilde çalışması için 86Box'ın bu makinenin başka bir konuma taşındığını mı yoksa kopyalandığını mı belirlemesi gerekmektedir.\n" +"\n" +"Bundan emin değilseniz \"Kopyalandı\" seçeneğini seçin." msgid "I Moved It" msgstr "Taşındı" @@ -1315,7 +1387,7 @@ msgid "I Copied It" msgstr "Kopyalandı" msgid "86Box Monitor #" -msgstr "86Box monitör " +msgstr "86Box Monitör #" msgid "No MCA devices." msgstr "MCA cihazı yok." @@ -1324,16 +1396,16 @@ msgid "MiB" msgstr "MiB" msgid "Network Card #1" -msgstr "Ağ kartı 1" +msgstr "1. Ağ Kartı" msgid "Network Card #2" -msgstr "Ağ kartı 2" +msgstr "2. Ağ Kartı" msgid "Network Card #3" -msgstr "Ağ kartı 3" +msgstr "3. Ağ Kartı" msgid "Network Card #4" -msgstr "Ağ kartı 4" +msgstr "4. Ağ Kartı" msgid "Mode:" msgstr "Mod:" @@ -1345,43 +1417,46 @@ msgid "Adapter:" msgstr "Adaptör:" msgid "VDE Socket:" -msgstr "VDE soketi:" +msgstr "VDE Soketi:" msgid "86Box Unit Tester" -msgstr "86Box birim test cihazı" +msgstr "86Box Test Cihazı" msgid "Novell NetWare 2.x Key Card" -msgstr "Novell NetWare 2.x anahtar kartı" +msgstr "Novell NetWare 2.x Anahtar Kartı" msgid "Serial port passthrough 1" -msgstr "Seri port geçişi 1" +msgstr "1. Seri Port geçişi" msgid "Serial port passthrough 2" -msgstr "Seri port geçişi 2" +msgstr "2. Seri Port geçişi" msgid "Serial port passthrough 3" -msgstr "Seri port geçişi 3" +msgstr "3. Seri Port geçişi" msgid "Serial port passthrough 4" -msgstr "Seri port geçişi 4" +msgstr "4. Seri Port geçişi" msgid "Renderer options..." -msgstr "İşleyici seçenekleri..." +msgstr "Derleyici seçenekleri..." msgid "Logitech/Microsoft Bus Mouse" -msgstr "Logitech/Microsoft veri yolu bağlantılı fare" +msgstr "Logitech/Microsoft Bus Fare" msgid "Microsoft Bus Mouse (InPort)" -msgstr "Microsoft veri yolu bağlantılı fare (InPort)" +msgstr "Microsoft Bus Fare (InPort)" msgid "Mouse Systems Serial Mouse" -msgstr "Mouse Systems seri fare" +msgstr "Mouse Systems Seri Fare" + +msgid "Mouse Systems Bus Mouse" +msgstr "Mouse Systems Bus Fare" msgid "Microsoft Serial Mouse" -msgstr "Microsoft seri fare" +msgstr "Microsoft Seri Fare" msgid "Logitech Serial Mouse" -msgstr "Logitech seri fare" +msgstr "Logitech Seri Fare" msgid "PS/2 Mouse" msgstr "PS/2 fare" @@ -1390,34 +1465,34 @@ msgid "3M MicroTouch (Serial)" msgstr "3M MicroTouch (seri)" msgid "[COM] Standard Hayes-compliant Modem" -msgstr "[COM] Standart Hayes uyumlu modem" +msgstr "[COM] Standart Hayes Uyumlu Modem" msgid "Roland MT-32 Emulation" -msgstr "Roland MT-32 emülasyonu" +msgstr "Roland MT-32 Emülasyonu" msgid "Roland MT-32 (New) Emulation" -msgstr "Roland MT-32 (yeni) emülasyonu" +msgstr "Roland MT-32 (Yeni) Emülasyonu" msgid "Roland CM-32L Emulation" -msgstr "Roland CM-32L emülasyonu" +msgstr "Roland CM-32L Emülasyonu" msgid "Roland CM-32LN Emulation" -msgstr "Roland CM-32LN emülasyonu" +msgstr "Roland CM-32LN Emülasyonu" msgid "OPL4-ML Daughterboard" -msgstr "OPL4-ML yankartı" +msgstr "OPL4-ML Yankartı" msgid "System MIDI" msgstr "Sistem MIDI'si" msgid "MIDI Input Device" -msgstr "MIDI giriş cihazı" +msgstr "MIDI Giriş Cihazı" msgid "BIOS Address" -msgstr "BIOS adresi" +msgstr "BIOS Adresi" msgid "Enable BIOS extension ROM Writes" -msgstr "BIOS uzantı ROM'larına yazmayı etkinleştir" +msgstr "BIOS uzantı ROM yazımlarını etkinleştir" msgid "Address" msgstr "Adres" @@ -1426,7 +1501,7 @@ msgid "IRQ" msgstr "IRQ" msgid "BIOS Revision" -msgstr "BIOS sürümü" +msgstr "BIOS Sürümü" msgid "Translate 26 -> 17" msgstr "26 -> 17 olarak çevir" @@ -1438,91 +1513,91 @@ msgid "Enable backlight" msgstr "Arka ışığı etkinleştir" msgid "Invert colors" -msgstr "Renkleri ters çevir" +msgstr "Renkleri tersine çevir" msgid "BIOS size" msgstr "BIOS boyutu" msgid "Map C0000-C7FFF as UMB" -msgstr "C0000-C7FFF'yi UMB olarak eşleyin" +msgstr "C0000-C7FFF'yi UMB olarak eşle" msgid "Map C8000-CFFFF as UMB" -msgstr "C8000-CFFFF'yi UMB olarak eşleyin" +msgstr "C8000-CFFFF'yi UMB olarak eşle" msgid "Map D0000-D7FFF as UMB" -msgstr "D0000-D7FFF'yi UMB olarak eşleyin" +msgstr "D0000-D7FFF'yi UMB olarak eşle" msgid "Map D8000-DFFFF as UMB" -msgstr "D8000-DFFFF'yi UMB olarak eşleyin" +msgstr "D8000-DFFFF'yi UMB olarak eşle" msgid "Map E0000-E7FFF as UMB" -msgstr "E0000-E7FFF'yi UMB olarak eşleyin" +msgstr "E0000-E7FFF'yi UMB olarak eşle" msgid "Map E8000-EFFFF as UMB" -msgstr "E8000-EFFFF'yi UMB olarak eşleyin" +msgstr "E8000-EFFFF'yi UMB olarak eşle" msgid "JS9 Jumper (JIM)" -msgstr "JS9 jumper'ı (JIM)" +msgstr "JS9 Jumper'ı (JIM)" msgid "MIDI Output Device" -msgstr "MIDI çıkış cihazı" +msgstr "MIDI Çıkış Cihazı" msgid "MIDI Real time" -msgstr "Gerçek zamanlı MIDI" +msgstr "MIDI Gerçek Zamanı" msgid "MIDI Thru" -msgstr "MIDI geçişi" +msgstr "MIDI Geçişi" msgid "MIDI Clockout" -msgstr "MIDI saat çıkışı" +msgstr "MIDI Saat Çıkışı" msgid "SoundFont" msgstr "SoundFont" msgid "Output Gain" -msgstr "Çıkış ses düzeyi kazancı" +msgstr "Çıkış Sesi Artışı" msgid "Chorus" msgstr "Koro" msgid "Chorus Voices" -msgstr "Koro sesleri" +msgstr "Koro Sesleri" msgid "Chorus Level" msgstr "Koro seviyesi" msgid "Chorus Speed" -msgstr "Koro hızı" +msgstr "Koro Hızı" msgid "Chorus Depth" -msgstr "Koro derinliği" +msgstr "Koro Derinliği" msgid "Chorus Waveform" -msgstr "Koro dalga biçimi" +msgstr "Koro Dalga Biçimi" msgid "Reverb" msgstr "Yankı" msgid "Reverb Room Size" -msgstr "Yankı odası boyutu" +msgstr "Yankı Odası Boyutu" msgid "Reverb Damping" -msgstr "Yankı sönümleme" +msgstr "Yankı Sönümleme" msgid "Reverb Width" -msgstr "Yankı genişliği" +msgstr "Yankı Genişliği" msgid "Reverb Level" -msgstr "Yankı seviyesi" +msgstr "Yankı Seviyesi" msgid "Interpolation Method" -msgstr "İnterpolasyon yöntemi" +msgstr "İnterpolasyon Yöntemi" msgid "Reverb Output Gain" -msgstr "Yankı çıkış ses düzeyi artışı" +msgstr "Yankı Çıkış Sesi Artışı" msgid "Reversed stereo" -msgstr "Tersine çevrilmiş stereo" +msgstr "Tersine çevirilmiş stereo" msgid "Nice ramp" msgstr "Güzel rampa" @@ -1534,34 +1609,34 @@ msgid "Buttons" msgstr "Düğmeler" msgid "Serial Port" -msgstr "Seri port" +msgstr "Seri Port" msgid "RTS toggle" -msgstr "RTS geçişi" +msgstr "RTS ayarı" msgid "Revision" msgstr "Sürüm" msgid "Controller" -msgstr "Kontrolcü" +msgstr "Denetleyici" msgid "Show Crosshair" -msgstr "Nişangahı göster" +msgstr "Nişangahı Göster" msgid "DMA" msgstr "DMA" msgid "MAC Address" -msgstr "MAC adresi" +msgstr "MAC Adresi" msgid "MAC Address OUI" -msgstr "MAC adresinin OUI'si" +msgstr "MAC Adresinin OUI'ı" msgid "Enable BIOS" -msgstr "BIOS'u etkinleştir" +msgstr "BIOS'u Etkinleştir" msgid "Baud Rate" -msgstr "Baud hızı" +msgstr "Baud Hızı" msgid "TCP/IP listening port" msgstr "TCP/IP dinleme portu" @@ -1573,37 +1648,37 @@ msgid "Telnet emulation" msgstr "Telnet emülasyonu" msgid "RAM Address" -msgstr "RAM adresi" +msgstr "Bellek (RAM) Adresi" msgid "RAM size" -msgstr "RAM boyutu" +msgstr "Bellek (RAM) Boyutu" msgid "Initial RAM size" -msgstr "İlk RAM boyutu" +msgstr "İlk Bellek (RAM) boyutu" msgid "Serial Number" -msgstr "Seri numarası" +msgstr "Seri Numarası" msgid "Host ID" -msgstr "Ana bilgisayar kimliği" +msgstr "Ana sistemin kimliği" msgid "FDC Address" -msgstr "FDC adresi" +msgstr "FDC Adresi" msgid "MPU-401 Address" -msgstr "MPU-401 adresi" +msgstr "MPU-401 Adresi" msgid "MPU-401 IRQ" msgstr "MPU-401 IRQ" msgid "Receive MIDI input" -msgstr "MIDI girişi al" +msgstr "MIDI girişini dinle" msgid "Low DMA" msgstr "Düşük DMA" msgid "Enable Game port" -msgstr "Gameport girişini etkinleştir" +msgstr "Gameport'ı etkinleştir" msgid "Surround module" msgstr "Surround modülü" @@ -1654,7 +1729,7 @@ msgid "EMU8000 Address" msgstr "EMU8000 adresi" msgid "IDE Controller" -msgstr "IDE Kontrolcüsü" +msgstr "IDE Denetleyicisi" msgid "Codec" msgstr "Codec" @@ -1720,13 +1795,13 @@ msgid "Texture memory size" msgstr "Doku bellek boyutu" msgid "Dither subtraction" -msgstr "Dither çıkarma" +msgstr "Dither çıkarışı" msgid "Screen Filter" msgstr "Ekran filtresi" msgid "Render threads" -msgstr "İşleme için iş parçacığı sayısı" +msgstr "Derleme için iş parçacığı sayısı" msgid "SLI" msgstr "SLI" @@ -1768,7 +1843,7 @@ msgid "64 kB starting from F0000" msgstr "F0000'dan başlayarak 64 KB" msgid "128 kB starting from E0000 (address MSB inverted, last 64KB first)" -msgstr "E0000'dan başlayarak 128 kB (adres MSB ters çevrilmiş, önce son 64KB)" +msgstr "E0000'dan başlayarak 128 kB (adresin MSB'si ters çevirilmiş, önce sondaki 64KB)" msgid "Sine" msgstr "Sinüs" @@ -1786,10 +1861,10 @@ msgid "7th Order" msgstr "7. sıra" msgid "Non-timed (original)" -msgstr "Zamanlayıcı olmadan (orijinal)" +msgstr "Zamanlanmamış (orijinal)" msgid "45 Hz (JMP2 not populated)" -msgstr "45 Hz (JMP2'de jumper yok)" +msgstr "45 Hz (JMP2 kullanılmadan)" msgid "Two" msgstr "İki" @@ -1801,16 +1876,16 @@ msgid "Wheel" msgstr "Tekerlek" msgid "Five + Wheel" -msgstr "Beş + tekerlek" +msgstr "Beş +Tekerlek" msgid "Five + 2 Wheels" msgstr "" msgid "A3 - SMT2 Serial / SMT3(R)V" -msgstr "A3 - SMT2 seri / SMT3(R)V" +msgstr "A3 - SMT2 Seri / SMT3(R)V" msgid "Q1 - SMT3(R) Serial" -msgstr "Q1 - SMT3(R) seri" +msgstr "Q1 - SMT3(R) Seri" msgid "8 KB" msgstr "8 KB" @@ -1825,7 +1900,7 @@ msgid "64 KB" msgstr "64 KB" msgid "Disable BIOS" -msgstr "BIOS'u devre dışı bırak" +msgstr "BIOS'u Devre Dışı Bırak" msgid "512 KB" msgstr "512 KB" @@ -1876,25 +1951,25 @@ msgid "New" msgstr "Yeni" msgid "Color (generic)" -msgstr "Renk (sıradan)" +msgstr "Çok Renkli (genel)" msgid "Green Monochrome" -msgstr "Yeşil monokrom" +msgstr "Yeşil Renkli" msgid "Amber Monochrome" -msgstr "Kehribar monokrom" +msgstr "Kehribar Renkli" msgid "Gray Monochrome" -msgstr "Gri monokrom" +msgstr "Gri Renkli" msgid "Color (no brown)" -msgstr "Renk (kahverengi yok)" +msgstr "Çok Renkli (kahverengi yok)" msgid "Color (IBM 5153)" -msgstr "Renkli (IBM 5153)" +msgstr "Çok Renkli (IBM 5153)" msgid "Simple doubling" -msgstr "Basit ikiye katlama" +msgstr "Basit katlama" msgid "sRGB interpolation" msgstr "sRGB interpolasyonu" @@ -1906,25 +1981,25 @@ msgid "128 KB" msgstr "128 KB" msgid "Monochrome (5151/MDA) (white)" -msgstr "Monokrom (5151/MDA) (beyaz)" +msgstr "Tek Renkli (5151/MDA) (beyaz)" msgid "Monochrome (5151/MDA) (green)" -msgstr "Monokrom (5151/MDA) (yeşil)" +msgstr "Tek Renkli (5151/MDA) (yeşil)" msgid "Monochrome (5151/MDA) (amber)" -msgstr "Monokrom (5151/MDA) (kehribar)" +msgstr "Tek Renkli (5151/MDA) (kehribar)" msgid "Color 40x25 (5153/CGA)" -msgstr "Renkli 40x25 (5153/CGA)" +msgstr "Çok Renkli 40x25 (5153/CGA)" msgid "Color 80x25 (5153/CGA)" -msgstr "Renkli 80x25 (5153/CGA)" +msgstr "Çok Renkli 80x25 (5153/CGA)" msgid "Enhanced Color - Normal Mode (5154/ECD)" -msgstr "Geliştirilmiş renkli - Normal mod (5154/ECD)" +msgstr "Gelişmiş Renkli - Normal Mod (5154/ECD)" msgid "Enhanced Color - Enhanced Mode (5154/ECD)" -msgstr "Geliştirilmiş renkli - Geliştirilmiş mod (5154/ECD)" +msgstr "Gelişmiş Renkli - Gelişmiş Mod (5154/ECD)" msgid "Green" msgstr "Yeşil" @@ -1948,16 +2023,16 @@ msgid "Other languages" msgstr "Diğer diller" msgid "Bochs latest" -msgstr "Bochs en son sürümü" +msgstr "Bochs'un en son sürümü" msgid "Mono Non-Interlaced" -msgstr "Monokrom (geçmeli tarama yok)" +msgstr "Tek Renkli (Geçiş Taramasız)" msgid "Color Interlaced" -msgstr "Renkli (geçmeli tarama var)" +msgstr "Çok Renkli (Geçiş Taramalı)" msgid "Color Non-Interlaced" -msgstr "Renkli (geçmeli tarama yok)" +msgstr "Çok Renkli (Geçiş Taramasız)" msgid "3Dfx Voodoo Graphics" msgstr "3Dfx Voodoo Grafikleri" @@ -1990,31 +2065,31 @@ msgid "Stereo LPT DAC" msgstr "Stereo LPT DAC" msgid "Generic Text Printer" -msgstr "Sıradan metin yazıcı" +msgstr "Genel Metin Yazıcı" -msgid "Generic ESC/P Dot-Matrix Printer" -msgstr "Sıradan ESC/P Dot Matrix yazıcı" +msgid "Generic ESC/P Dot-Matrix" +msgstr "Genel ESC/P Dot-Matrix" msgid "Generic PostScript Printer" -msgstr "Sıradan PostScript yazıcı" +msgstr "Genel PostScript Yazıcı" msgid "Generic PCL5e Printer" -msgstr "Sıradan PCL5e yazıcı" +msgstr "Genel PCL5e Yazıcı" msgid "Parallel Line Internet Protocol" msgstr "Paralel Hat İnternet Protokolü" msgid "Protection Dongle for Savage Quest" -msgstr "Savage Quest için koruma dongle'ı" +msgstr "Savage Quest için Koruma Kilidi" msgid "Serial Passthrough Device" -msgstr "Seri port geçiş cihazı" +msgstr "Seri Geçiş Cihazı" msgid "Passthrough Mode" -msgstr "Geçişli mod" +msgstr "Geçiş Modu" msgid "Host Serial Device" -msgstr "Ana bilgisayar seri cihazı" +msgstr "Ana Sistemdeki Seri Cihaz" msgid "Name of pipe" msgstr "Boru adı" @@ -2026,16 +2101,16 @@ msgid "Stop bits" msgstr "Dur bitleri" msgid "Baud Rate of Passthrough" -msgstr "Geçiş Baud hızı" +msgstr "Geçişin Baud Hızı" msgid "Named Pipe (Server)" -msgstr "Adlandırılmış boru (Sunucu)" +msgstr "Adlandırılmış Boru (Sunucu)" msgid "Host Serial Passthrough" -msgstr "Ana bilgisayar seri port geçişi" +msgstr "Ana Sistem Seri Geçişi" msgid "E&ject %1" -msgstr "%1 diskini &çıkar" +msgstr "%1 imajını &çıkar" msgid "&Unmute" msgstr "&Sesi aç" @@ -2044,31 +2119,31 @@ msgid "Softfloat FPU" msgstr "Softfloat FPU" msgid "High performance impact" -msgstr "Ciddi performans düşüklüğüne neden olabilir" +msgstr "Ciddi performans azalışına neden olabilir" msgid "[Generic] RAM Disk (max. speed)" -msgstr "[Generic] RAM Disk (maks. hız)" +msgstr "[Genel] RAM Disk (maks. hız)" msgid "[Generic] 1989 (3500 RPM)" -msgstr "" +msgstr "[Genel] 1989 (3500 RPM)" msgid "[Generic] 1992 (3600 RPM)" -msgstr "" +msgstr "[Genel] 1992 (3600 RPM)" msgid "[Generic] 1994 (4500 RPM)" -msgstr "" +msgstr "[Genel] 1994 (4500 RPM)" msgid "[Generic] 1996 (5400 RPM)" -msgstr "" +msgstr "[Genel] 1996 (5400 RPM)" msgid "[Generic] 1997 (5400 RPM)" -msgstr "" +msgstr "[Genel] 1997 (5400 RPM)" msgid "[Generic] 1998 (5400 RPM)" -msgstr "" +msgstr "[Genel] 1998 (5400 RPM)" msgid "[Generic] 2000 (7200 RPM)" -msgstr "" +msgstr "[Genel] 2000 (7200 RPM)" msgid "IBM 8514/A clone (ISA)" msgstr "IBM 8514/A klonu (ISA)" @@ -2077,73 +2152,79 @@ msgid "Vendor" msgstr "Üretici" msgid "Generic PC/XT Memory Expansion" -msgstr "Sıradan PC/XT bellek artırma" +msgstr "Genel PC/XT Bellek Artırıcı" msgid "Generic PC/AT Memory Expansion" -msgstr "Sıradan PC/AT bellek artırma" +msgstr "Genel PC/AT Bellek Artırıcı" msgid "Unable to find Dot-Matrix fonts" -msgstr "Dot Matrix yazı tipleri bulunamıyor" +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." +msgstr "Genel ESC/P Dot-Matrix yazıcısının emülasyonu için \"roms/printer/fonts\" dizininde TrueType yazı tiplerinin bulunması gereklidir." msgid "Inhibit multimedia keys" -msgstr "" +msgstr "Multimedya tuşlarını engelle" msgid "Ask for confirmation before saving settings" -msgstr "" +msgstr "Ayarları kaydetmeden once onay için sor" msgid "Ask for confirmation before hard resetting" -msgstr "" +msgstr "Yeniden başlamaya zorlamadan önce onay için sor" msgid "Ask for confirmation before quitting" -msgstr "" +msgstr "Çıkış yapmadan once onay için sor" msgid "Options" -msgstr "" +msgstr "Seçenekler" msgid "Model" -msgstr "" +msgstr "Model" msgid "Model:" -msgstr "" +msgstr "Model:" msgid "Failed to initialize Vulkan renderer." -msgstr "" +msgstr "Vulkan derleyicisi başlatılamadı." msgid "GLSL Error" -msgstr "" +msgstr "GLSL Hatası" msgid "Could not load shader: %1" -msgstr "" +msgstr "%1 gölgelendiricisi yüklenemedi" msgid "OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2" -msgstr "" +msgstr "OpenGL sürüm 3.0 veya daha yükseği gereklidir. Şu anki GLSL sürümü %1.%2" msgid "Could not load texture: %1" -msgstr "" +msgstr "%1 dokusu yüklenemedi" -msgid "Could not compile shader:\n\n%1" -msgstr "" +msgid "" +"Could not compile shader:\n" +"\n" +"%1" +msgstr "%1 gölgelendiricisi derlenemedi" -msgid "Program not linked:\n\n%1" -msgstr "" +msgid "" +"Program not linked:\n" +"\n" +"%1" +msgstr "%1 programı bağlanamadı" msgid "Shader Manager" -msgstr "" +msgstr "Gölgelendirici Yöneticisi" msgid "Shader Configuration" -msgstr "" +msgstr "Gölgelendirici Seçenekleri" msgid "Add" -msgstr "" +msgstr "Ekle" msgid "Move up" -msgstr "" +msgstr "Yukarı taşı" msgid "Move down" -msgstr "" +msgstr "Aşağı taşı" msgid "Could not load file %1" -msgstr "" +msgstr "%1 dosyası yüklenemedi" \ No newline at end of file diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index eb7d6ac44..b3b880094 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -56,6 +56,10 @@ extern "C" { #include <86box/gdbstub.h> #include <86box/version.h> #include <86box/renderdefs.h> +#ifdef Q_OS_LINUX +#define GAMEMODE_AUTO +#include "../unix/gamemode/gamemode_client.h" +#endif } #ifdef Q_OS_WINDOWS @@ -102,6 +106,8 @@ bool cpu_thread_running = false; void qt_set_sequence_auto_mnemonic(bool b); #ifdef Q_OS_WINDOWS +bool acp_utf8 = false; + static void keyboard_getkeymap() { @@ -435,6 +441,9 @@ main_thread_fn() int frames; QThread::currentThread()->setPriority(QThread::HighestPriority); +#ifdef _WIN32 + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); +#endif plat_set_thread_name(nullptr, "main_thread_fn"); framecountx = 0; // title_update = 1; @@ -446,14 +455,14 @@ main_thread_fn() const uint64_t new_time = elapsed_timer.elapsed(); #ifdef USE_GDBSTUB if (gdbstub_next_asap && (drawits <= 0)) - drawits = 10; + drawits = force_10ms ? 10 : 1; else #endif drawits += static_cast(new_time - old_time); old_time = new_time; if (drawits > 0 && !dopause) { /* Yes, so do one frame now. */ - drawits -= 10; + drawits -= force_10ms ? 10 : 1; if (drawits > 50) drawits = 0; @@ -472,8 +481,8 @@ main_thread_fn() break; } #endif - /* Every 200 frames we save the machine status. */ - if (++frames >= 200 && nvr_dosave) { + /* Every 2 emulated seconds we save the machine status. */ + if (++frames >= (force_10ms ? 200 : 2000) && nvr_dosave) { qt_nvr_save(); nvr_dosave = 0; frames = 0; @@ -515,6 +524,13 @@ extern bool windows_is_light_theme(); int main(int argc, char *argv[]) { +#ifdef Q_OS_WINDOWS + /* Check if Windows supports UTF-8 */ + if (GetACP() == CP_UTF8) + acp_utf8 = 1; + else + acp_utf8 = 0; +#endif #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, false); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); @@ -530,6 +546,9 @@ main(int argc, char *argv[]) #ifdef Q_OS_WINDOWS Q_INIT_RESOURCE(darkstyle); + if (QFile(QApplication::applicationDirPath() + "/opengl32.dll").exists()) { + qputenv("QT_OPENGL_DLL", QFileInfo(QApplication::applicationDirPath() + "/opengl32.dll").absoluteFilePath().toUtf8()); + } QApplication::setAttribute(Qt::AA_NativeWindows); if (!windows_is_light_theme()) { @@ -788,6 +807,8 @@ main(int argc, char *argv[]) }); QObject::connect(main_window, &MainWindow::vmmRunningStateChanged, &manager_socket, &VMManagerClientSocket::clientRunningStateChanged); main_window->installEventFilter(&manager_socket); + + manager_socket.sendWinIdMessage(main_window->winId()); } // pc_reset_hard_init(); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 6f87c3ce0..861037f99 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1454,11 +1454,13 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event) if (receiver == this) { static auto curdopause = dopause; if (event->type() == QEvent::WindowBlocked) { + window_blocked = true; curdopause = dopause; plat_pause(isShowMessage ? 2 : 1); emit setMouseCapture(false); releaseKeyboard(); } else if (event->type() == QEvent::WindowUnblocked) { + window_blocked = false; plat_pause(curdopause); } } @@ -2112,7 +2114,7 @@ MainWindow::updateUiPauseState() QString(tr("Pause execution")); ui->actionPause->setIcon(pause_icon); ui->actionPause->setToolTip(tooltip_text); - emit vmmRunningStateChanged(static_cast(dopause)); + emit vmmRunningStateChanged(static_cast(window_blocked ? (dopause ? VMManagerProtocol::RunningState::PausedWaiting : VMManagerProtocol::RunningState::RunningWaiting) : (VMManagerProtocol::RunningState)dopause)); } void diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 54a04a975..370d97d0e 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -200,6 +200,7 @@ private: QIcon caps_icon_off, scroll_icon_off, num_icon_off, kana_icon_off; bool isShowMessage = false; + bool window_blocked = false; }; #endif // QT_MAINWINDOW_HPP diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 8677a6a91..a2c0bc410 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -177,14 +177,28 @@ do_stop(void) #endif } +extern bool acp_utf8; void plat_get_exe_name(char *s, int size) { +#ifdef Q_OS_WINDOWS + wchar_t *temp; + + if (acp_utf8) + GetModuleFileNameA(NULL, s, size); + else { + temp = (wchar_t*)calloc(size, sizeof(wchar_t)); + GetModuleFileNameW(NULL, temp, size); + c16stombs(s, (uint16_t*)temp, size); + free(temp); + } +#else QByteArray exepath_temp = QCoreApplication::applicationDirPath().toLocal8Bit(); memcpy(s, exepath_temp.data(), std::min((qsizetype) exepath_temp.size(), (qsizetype) size)); path_slash(s); +#endif } uint32_t diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 5256de3d6..821b4c741 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -166,6 +166,10 @@ int ignoreNextMouseEvent = 1; void RendererStack::mouseReleaseEvent(QMouseEvent *event) { +#ifdef Q_OS_WINDOWS + rw_hwnd = (HWND) this->winId(); +#endif + if (!dopause && this->geometry().contains(m_monitor_index >= 1 ? event->globalPos() : event->pos()) && (event->button() == Qt::LeftButton) && !mouse_capture && (isMouseDown & 1) && (kbd_req_capture || (mouse_get_buttons() != 0)) && @@ -410,14 +414,8 @@ RendererStack::createRenderer(Renderer renderer) #endif } 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_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 83e19aec7..e50f4ebe1 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -152,11 +152,8 @@ SettingsDisplay::on_pushButtonConfigure8514_clicked() void SettingsDisplay::on_pushButtonConfigureXga_clicked() { - if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) { + if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) DeviceConfig::ConfigureDevice(&xga_device); - } else { - DeviceConfig::ConfigureDevice(&xga_isa_device); - } } void @@ -189,7 +186,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) bool videoCardHasXga = ((videoCard[0] == VID_INTERNAL) ? machine_has_flags(machineId, MACHINE_VIDEO_XGA) : (video_card_get_flags(videoCard[0]) == VIDEO_FLAG_TYPE_XGA)); bool machineSupports8514 = ((machineHasIsa16 || machineHasMca) && !videoCardHas8514); - bool machineSupportsXga = (((machineHasIsa16 && device_available(&xga_isa_device)) || (machineHasMca && device_available(&xga_device))) && !videoCardHasXga); + bool machineSupportsXga = ((machineHasMca && device_available(&xga_device)) && !videoCardHasXga); bool machineSupportsDa2 = machineHasMca && device_available(&ps55da2_device); ui->checkBox8514->setEnabled(machineSupports8514); diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index fb5576f69..0063ac727 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -117,6 +117,9 @@ SettingsMachine::SettingsMachine(QWidget *parent) ui->comboBoxMachineType->setCurrentIndex(-1); ui->comboBoxMachineType->setCurrentIndex(selectedMachineType); + ui->radioButtonLargerFrames->setChecked(force_10ms); + ui->radioButtonSmallerFrames->setChecked(!force_10ms); + #ifndef USE_DYNAREC ui->checkBoxDynamicRecompiler->setEnabled(false); ui->checkBoxDynamicRecompiler->setVisible(false); @@ -137,6 +140,7 @@ SettingsMachine::save() fpu_type = ui->comboBoxFPU->currentData().toInt(); cpu_use_dynarec = ui->checkBoxDynamicRecompiler->isChecked() ? 1 : 0; fpu_softfloat = ui->checkBoxFPUSoftfloat->isChecked() ? 1 : 0; + force_10ms = ui->radioButtonLargerFrames->isChecked() ? 1 : 0; int64_t temp_mem_size; if (machine_get_ram_granularity(machine) < 1024) @@ -359,3 +363,15 @@ void SettingsMachine::on_checkBoxFPUSoftfloat_stateChanged(int state) { ui->softFloatWarningText->setVisible(false); } } + +void SettingsMachine::on_radioButtonSmallerFrames_clicked() +{ + ui->radioButtonLargerFrames->setChecked(false); +} + + +void SettingsMachine::on_radioButtonLargerFrames_clicked() +{ + ui->radioButtonSmallerFrames->setChecked(false); +} + diff --git a/src/qt/qt_settingsmachine.hpp b/src/qt/qt_settingsmachine.hpp index 864894447..36ece7f18 100644 --- a/src/qt/qt_settingsmachine.hpp +++ b/src/qt/qt_settingsmachine.hpp @@ -28,6 +28,10 @@ private slots: void on_comboBoxMachineType_currentIndexChanged(int index); void on_checkBoxFPUSoftfloat_stateChanged(int state); + void on_radioButtonSmallerFrames_clicked(); + + void on_radioButtonLargerFrames_clicked(); + private: Ui::SettingsMachine *ui; }; diff --git a/src/qt/qt_settingsmachine.ui b/src/qt/qt_settingsmachine.ui index e3b3cdbde..f677ea178 100644 --- a/src/qt/qt_settingsmachine.ui +++ b/src/qt/qt_settingsmachine.ui @@ -41,7 +41,6 @@ 0 - @@ -49,7 +48,6 @@ - @@ -57,7 +55,6 @@ - @@ -65,7 +62,6 @@ - @@ -73,7 +69,6 @@ - @@ -84,7 +79,6 @@ - @@ -92,7 +86,6 @@ - @@ -100,7 +93,6 @@ - @@ -129,18 +121,16 @@ - Frequency: - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter - @@ -157,7 +147,6 @@ - @@ -165,7 +154,6 @@ - @@ -173,7 +161,6 @@ - @@ -196,7 +183,6 @@ - @@ -213,7 +199,6 @@ - @@ -268,7 +253,6 @@ - @@ -286,7 +270,6 @@ - @@ -302,7 +285,6 @@ - @@ -310,7 +292,6 @@ - @@ -321,7 +302,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -333,7 +314,6 @@ - @@ -345,25 +325,57 @@ Time synchronization - - + + Disabled - + + + + Enabled (UTC) + + + + Enabled (local time) + + + + + + + + 0 + 0 + + + + CPU frame size + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + - + - Enabled (UTC) + Larger frames (less smooth) + + + + + + + Smaller frames (smoother) @@ -373,7 +385,7 @@ - Qt::Vertical + Qt::Orientation::Vertical diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 9f97bacd6..2a8332f5c 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -94,6 +94,7 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) intf_label->setVisible(true); break; +#if defined(__unix__) || defined(__APPLE__) case NET_TYPE_TAP: // option_list_label->setText("TAP Options"); option_list_label->setVisible(true); @@ -101,6 +102,8 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) bridge_label->setVisible(true); bridge_line->setVisible(true); + break; +#endif case NET_TYPE_SLIRP: default: @@ -139,7 +142,9 @@ SettingsNetwork::save() for (int i = 0; i < NET_CARD_MAX; ++i) { auto *cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); +#if defined(__unix__) || defined(__APPLE__) auto *bridge_line = findChild(QString("bridgeTAPNIC%1").arg(i + 1)); +#endif net_cards_conf[i].device_num = cbox->currentData().toInt(); cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); net_cards_conf[i].net_type = cbox->currentData().toInt(); @@ -149,8 +154,10 @@ SettingsNetwork::save() 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) strncpy(net_cards_conf[i].host_dev_name, socket_line->text().toUtf8().constData(), sizeof(net_cards_conf[i].host_dev_name)); +#if defined(__unix__) || defined(__APPLE__) else if (net_cards_conf[i].net_type == NET_TYPE_TAP) strncpy(net_cards_conf[i].host_dev_name, bridge_line->text().toUtf8().constData(), sizeof(net_cards_conf[i].host_dev_name)); +#endif } } @@ -217,7 +224,9 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) if (network_devmap.has_vde) Models::AddEntry(model, "VDE", NET_TYPE_VDE); +#if defined(__unix__) || defined(__APPLE__) Models::AddEntry(model, "TAP", NET_TYPE_TAP); +#endif model->removeRows(0, removeRows); cbox->setCurrentIndex(cbox->findData(net_cards_conf[i].net_type)); @@ -243,10 +252,12 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) QString currentVdeSocket = net_cards_conf[i].host_dev_name; auto editline = findChild(QString("socketVDENIC%1").arg(i+1)); editline->setText(currentVdeSocket); +#if defined(__unix__) || defined(__APPLE__) } else if (net_cards_conf[i].net_type == NET_TYPE_TAP) { QString currentTapDevice = net_cards_conf[i].host_dev_name; auto editline = findChild(QString("bridgeTAPNIC%1").arg(i+1)); editline->setText(currentTapDevice); +#endif } } } diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index d282bcb8b..5c9b24c46 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -62,7 +62,6 @@ SettingsStorageControllers::save() ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0; ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0; cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0; - lba_enhancer_enabled = ui->checkBoxLbaEnhancer->isChecked() ? 1 : 0; } void @@ -232,9 +231,6 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) ui->checkBoxCassette->setChecked(false); ui->checkBoxCassette->setEnabled(false); } - - ui->checkBoxLbaEnhancer->setChecked(lba_enhancer_enabled > 0 && device_available(&lba_enhancer_device)); - ui->pushButtonConfigureLbaEnhancer->setEnabled(ui->checkBoxLbaEnhancer->isChecked()); } void @@ -365,15 +361,3 @@ SettingsStorageControllers::on_pushButtonSCSI4_clicked() { DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()), 4); } - -void -SettingsStorageControllers::on_checkBoxLbaEnhancer_stateChanged(int arg1) -{ - ui->pushButtonConfigureLbaEnhancer->setEnabled(arg1 != 0); -} - -void -SettingsStorageControllers::on_pushButtonConfigureLbaEnhancer_clicked() -{ - DeviceConfig::ConfigureDevice(&lba_enhancer_device); -} diff --git a/src/qt/qt_settingsstoragecontrollers.hpp b/src/qt/qt_settingsstoragecontrollers.hpp index 7c1c56086..074b48dbd 100644 --- a/src/qt/qt_settingsstoragecontrollers.hpp +++ b/src/qt/qt_settingsstoragecontrollers.hpp @@ -44,9 +44,6 @@ private slots: void on_comboBoxSCSI4_currentIndexChanged(int index); void on_pushButtonSCSI4_clicked(); - void on_checkBoxLbaEnhancer_stateChanged(int arg1); - void on_pushButtonConfigureLbaEnhancer_clicked(); - private: Ui::SettingsStorageControllers *ui; int machineId = 0; diff --git a/src/qt/qt_settingsstoragecontrollers.ui b/src/qt/qt_settingsstoragecontrollers.ui index cd1bf9baf..b9eb310ba 100644 --- a/src/qt/qt_settingsstoragecontrollers.ui +++ b/src/qt/qt_settingsstoragecontrollers.ui @@ -257,43 +257,6 @@ - - - - 0 - - - 0 - - - - - Vision Systems LBA Enhancer - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Configure - - - - - diff --git a/src/qt/qt_vmmanager_addmachine.cpp b/src/qt/qt_vmmanager_addmachine.cpp index 597c2ef11..aa6c7a1c4 100644 --- a/src/qt/qt_vmmanager_addmachine.cpp +++ b/src/qt/qt_vmmanager_addmachine.cpp @@ -59,7 +59,7 @@ VMManagerAddMachine(QWidget *parent) : QWizard(parent) // Wizard wants to resize based on image. This keeps the size setMinimumSize(size()); - setOption(HaveHelpButton, true); + setOption(HaveHelpButton, false); // setPixmap(LogoPixmap, QPixmap(":/settings/qt/icons/86Box-gray.ico")); connect(this, &QWizard::helpRequested, this, &VMManagerAddMachine::showHelp); diff --git a/src/qt/qt_vmmanager_clientsocket.cpp b/src/qt/qt_vmmanager_clientsocket.cpp index 1035a846c..f5e5c8bad 100644 --- a/src/qt/qt_vmmanager_clientsocket.cpp +++ b/src/qt/qt_vmmanager_clientsocket.cpp @@ -218,7 +218,9 @@ VMManagerClientSocket::eventFilter(QObject *obj, QEvent *event) if (event->type() == QEvent::WindowBlocked) { running_state = dopause ? VMManagerProtocol::RunningState::PausedWaiting : VMManagerProtocol::RunningState::RunningWaiting; clientRunningStateChanged(running_state); + window_blocked = true; } else if (event->type() == QEvent::WindowUnblocked) { + window_blocked = false; running_state = dopause ? VMManagerProtocol::RunningState::Paused : VMManagerProtocol::RunningState::Running; clientRunningStateChanged(running_state); } @@ -226,11 +228,22 @@ VMManagerClientSocket::eventFilter(QObject *obj, QEvent *event) return QObject::eventFilter(obj, event); } +void +VMManagerClientSocket::sendWinIdMessage(WId id) +{ + QJsonObject extra_object; + extra_object["params"] = static_cast(id); + sendMessageWithObject(VMManagerProtocol::ClientMessage::WinIdMessage, extra_object); +} + void VMManagerClientSocket::clientRunningStateChanged(VMManagerProtocol::RunningState state) const { QJsonObject extra_object; + if ((state == VMManagerProtocol::RunningState::Paused + || state == VMManagerProtocol::RunningState::Running) && window_blocked) { + state = (state == VMManagerProtocol::RunningState::Paused) ? VMManagerProtocol::RunningState::PausedWaiting : VMManagerProtocol::RunningState::RunningWaiting; + } extra_object["status"] = static_cast(state); sendMessageWithObject(VMManagerProtocol::ClientMessage::RunningStateChanged, extra_object); - } diff --git a/src/qt/qt_vmmanager_clientsocket.hpp b/src/qt/qt_vmmanager_clientsocket.hpp index 10a053347..980ec10ee 100644 --- a/src/qt/qt_vmmanager_clientsocket.hpp +++ b/src/qt/qt_vmmanager_clientsocket.hpp @@ -31,6 +31,8 @@ public: explicit VMManagerClientSocket(QObject* object = nullptr); bool IPCConnect(const QString &server); + void sendWinIdMessage(WId id); + signals: void pause(); void ctrlaltdel(); @@ -47,6 +49,7 @@ private: QString server_name; QLocalSocket *socket; bool server_connected; + bool window_blocked = false; void connected() const; void disconnected() const; static void connectionError(QLocalSocket::LocalSocketError socketError); diff --git a/src/qt/qt_vmmanager_details.cpp b/src/qt/qt_vmmanager_details.cpp index a834e35f8..c3b5ac4ce 100644 --- a/src/qt/qt_vmmanager_details.cpp +++ b/src/qt/qt_vmmanager_details.cpp @@ -336,6 +336,17 @@ VMManagerDetails::updateProcessStatus() { connect(startPauseButton, &QToolButton::clicked, sysconfig, &VMManagerSystem::startButtonPressed); startPauseButton->setToolTip(tr("Start")); } + + if (sysconfig->window_obscured) { + resetButton->setDisabled(true); + stopButton->setDisabled(true); + cadButton->setDisabled(true); + startPauseButton->setDisabled(true); + configureButton->setDisabled(true); + } else { + configureButton->setDisabled(false); + startPauseButton->setDisabled(false); + } } void diff --git a/src/qt/qt_vmmanager_main.cpp b/src/qt/qt_vmmanager_main.cpp index 8d59b0996..87649a6a1 100644 --- a/src/qt/qt_vmmanager_main.cpp +++ b/src/qt/qt_vmmanager_main.cpp @@ -48,7 +48,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) : // Set up the context menu for the list view ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->listView, &QListView::customContextMenuRequested, [this](const QPoint &pos) { + connect(ui->listView, &QListView::customContextMenuRequested, [this, parent](const QPoint &pos) { const auto indexAt = ui->listView->indexAt(pos); if (indexAt.isValid()) { QMenu contextMenu(tr("Context Menu"), ui->listView); @@ -59,6 +59,7 @@ VMManagerMain::VMManagerMain(QWidget *parent) : connect(&nameChangeAction, &QAction::triggered, ui->listView, [this, indexAt] { updateDisplayName(indexAt); }); + nameChangeAction.setEnabled(!selected_sysconfig->window_obscured); QAction openSystemFolderAction(tr("Open folder")); contextMenu.addAction(&openSystemFolderAction); @@ -82,6 +83,18 @@ VMManagerMain::VMManagerMain(QWidget *parent) : selected_sysconfig->setIcon(iconName); } }); + setSystemIcon.setEnabled(!selected_sysconfig->window_obscured); + + QAction killIcon(tr("&Kill")); + contextMenu.addAction(&killIcon); + connect(&killIcon, &QAction::triggered, [this, parent] { + QMessageBox msgbox(QMessageBox::Warning, tr("Warning"), tr("Killing a virtual machine can cause data loss. Only do this if 86Box.exe process gets stuck.\n\nDo you really wish to kill the virtual machine \"%1\"?").arg(selected_sysconfig->displayName), QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, parent); + msgbox.exec(); + if (msgbox.result() == QMessageBox::Yes) { + selected_sysconfig->process->kill(); + } + }); + killIcon.setEnabled(selected_sysconfig->process->state() == QProcess::Running); contextMenu.addSeparator(); @@ -131,12 +144,14 @@ VMManagerMain::VMManagerMain(QWidget *parent) : emit updateStatusRight(totalCountString()); }); +#if EMU_BUILD_NUM != 0 // Start update check after a slight delay QTimer::singleShot(1000, this, [this] { if(updateCheck) { backgroundUpdateCheckStart(); } }); +#endif } VMManagerMain::~VMManagerMain() { @@ -276,7 +291,9 @@ VMManagerMain::loadSettings() { const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); const auto lastSelection = config->getStringValue("last_selection"); +#if EMU_BUILD_NUM != 0 updateCheck = config->getStringValue("update_check").toInt(); +#endif regexSearch = config->getStringValue("regex_search").toInt(); const auto matches = ui->listView->model()->match(vm_model->index(0, 0), VMManagerModel::Roles::ConfigName, QVariant::fromValue(lastSelection)); @@ -453,10 +470,10 @@ VMManagerMain::onPreferencesUpdated() } } +#if EMU_BUILD_NUM != 0 void VMManagerMain::backgroundUpdateCheckStart() const { -#if EMU_BUILD_NUM != 0 auto updateChannel = UpdateCheck::UpdateChannel::CI; #ifdef RELEASE_BUILD updateChannel = UpdateCheck::UpdateChannel::Stable; @@ -465,7 +482,6 @@ VMManagerMain::backgroundUpdateCheckStart() const connect(updateCheck, &UpdateCheck::updateCheckComplete, this, &VMManagerMain::backgroundUpdateCheckComplete); connect(updateCheck, &UpdateCheck::updateCheckError, this, &VMManagerMain::backgroundUpdateCheckError); updateCheck->checkForUpdates(); -#endif } void @@ -483,6 +499,7 @@ VMManagerMain::backgroundUpdateCheckError(const QString &errorMsg) qDebug() << "Update check failed with the following error:" << errorMsg; // TODO: Update the status bar } +#endif void VMManagerMain::showTextFileContents(const QString &title, const QString &path) diff --git a/src/qt/qt_vmmanager_main.hpp b/src/qt/qt_vmmanager_main.hpp index c3c541b4f..fecee2009 100644 --- a/src/qt/qt_vmmanager_main.hpp +++ b/src/qt/qt_vmmanager_main.hpp @@ -69,7 +69,11 @@ public slots: void searchSystems(const QString &text) const; void newMachineWizard(); void addNewSystem(const QString &name, const QString &dir, const QString &configFile = {}); +#if __GNUC__ >= 11 [[nodiscard]] QStringList getSearchCompletionList() const; +#else + QStringList getSearchCompletionList() const; +#endif void modelDataChange(); void onPreferencesUpdated(); @@ -81,7 +85,9 @@ private: VMManagerSystem *selected_sysconfig; // VMManagerConfig *config; QSortFilterProxyModel *proxy_model; +#if EMU_BUILD_NUM != 0 bool updateCheck = false; +#endif bool regexSearch = false; // void updateSelection(const QItemSelection &selected, @@ -93,11 +99,15 @@ private: void loadSettings(); [[nodiscard]] bool currentSelectionIsValid() const; [[nodiscard]] QString totalCountString() const; +#if EMU_BUILD_NUM != 0 void backgroundUpdateCheckStart() const; +#endif void showTextFileContents(const QString &title, const QString &path); private slots: +#if EMU_BUILD_NUM != 0 void backgroundUpdateCheckComplete(const UpdateCheck::UpdateResult &result); void backgroundUpdateCheckError(const QString &errorMsg); +#endif }; #include diff --git a/src/qt/qt_vmmanager_mainwindow.cpp b/src/qt/qt_vmmanager_mainwindow.cpp index a6f598f58..d3533482b 100644 --- a/src/qt/qt_vmmanager_mainwindow.cpp +++ b/src/qt/qt_vmmanager_mainwindow.cpp @@ -181,3 +181,9 @@ VMManagerMainWindow::checkForUpdatesTriggered() const auto updateCheck = new UpdateCheckDialog(updateChannel); updateCheck->exec(); } + +void VMManagerMainWindow::on_actionExit_triggered() +{ + this->close(); +} + diff --git a/src/qt/qt_vmmanager_mainwindow.hpp b/src/qt/qt_vmmanager_mainwindow.hpp index 764ed5ef8..12ac5afb1 100644 --- a/src/qt/qt_vmmanager_mainwindow.hpp +++ b/src/qt/qt_vmmanager_mainwindow.hpp @@ -52,6 +52,8 @@ private slots: void preferencesTriggered(); static void checkForUpdatesTriggered(); + void on_actionExit_triggered(); + protected: void closeEvent(QCloseEvent *event) override; }; diff --git a/src/qt/qt_vmmanager_mainwindow.ui b/src/qt/qt_vmmanager_mainwindow.ui index e3e0a242d..0c8dac8bc 100644 --- a/src/qt/qt_vmmanager_mainwindow.ui +++ b/src/qt/qt_vmmanager_mainwindow.ui @@ -35,6 +35,8 @@ File + + @@ -204,6 +206,17 @@ Check for updates + + + + + + &Exit + + + QAction::MenuRole::QuitRole + + diff --git a/src/qt/qt_vmmanager_preferences.cpp b/src/qt/qt_vmmanager_preferences.cpp index 0730f875b..57f67c9b8 100644 --- a/src/qt/qt_vmmanager_preferences.cpp +++ b/src/qt/qt_vmmanager_preferences.cpp @@ -44,8 +44,12 @@ VMManagerPreferences(QWidget *parent) : ui(new Ui::VMManagerPreferences) } // TODO: Defaults +#if EMU_BUILD_NUM != 0 const auto configUpdateCheck = config->getStringValue("update_check").toInt(); ui->updateCheckBox->setChecked(configUpdateCheck); +#else + ui->updateCheckBox->setVisible(false); +#endif const auto useRegexSearch = config->getStringValue("regex_search").toInt(); ui->regexSearchCheckBox->setChecked(useRegexSearch); @@ -70,7 +74,9 @@ VMManagerPreferences::accept() { const auto config = new VMManagerConfig(VMManagerConfig::ConfigType::General); config->setStringValue("system_directory", ui->systemDirectory->text()); +#if EMU_BUILD_NUM != 0 config->setStringValue("update_check", ui->updateCheckBox->isChecked() ? "1" : "0"); +#endif config->setStringValue("regex_search", ui->regexSearchCheckBox->isChecked() ? "1" : "0"); QDialog::accept(); } @@ -79,4 +85,4 @@ void VMManagerPreferences::reject() { QDialog::reject(); -} \ No newline at end of file +} diff --git a/src/qt/qt_vmmanager_protocol.cpp b/src/qt/qt_vmmanager_protocol.cpp index 26f8a1f93..ca862a55a 100644 --- a/src/qt/qt_vmmanager_protocol.cpp +++ b/src/qt/qt_vmmanager_protocol.cpp @@ -91,6 +91,8 @@ VMManagerProtocol::getClientMessageType(const QJsonObject &json_document) return VMManagerProtocol::ClientMessage::WindowUnblocked; } else if (message_type == "RunningStateChanged") { return VMManagerProtocol::ClientMessage::RunningStateChanged; + } else if (message_type == "WinIdMessage") { + return VMManagerProtocol::ClientMessage::WinIdMessage; } return VMManagerProtocol::ClientMessage::UnknownMessage; } diff --git a/src/qt/qt_vmmanager_protocol.hpp b/src/qt/qt_vmmanager_protocol.hpp index 48f0a2d8f..f50c37ae3 100644 --- a/src/qt/qt_vmmanager_protocol.hpp +++ b/src/qt/qt_vmmanager_protocol.hpp @@ -54,6 +54,7 @@ public: WindowBlocked, WindowUnblocked, RunningStateChanged, + WinIdMessage, UnknownMessage, }; Q_ENUM(ClientMessage); @@ -82,6 +83,7 @@ public: static bool hasRequiredFields(const QJsonObject &json_document); static QJsonObject getParams(const QJsonObject &json_document); + static QJsonObject getStatus(const QJsonObject &json_document); static ClientMessage getClientMessageType(const QJsonObject &json_document); static ManagerMessage getManagerMessageType(const QJsonObject &json_document); diff --git a/src/qt/qt_vmmanager_serversocket.cpp b/src/qt/qt_vmmanager_serversocket.cpp index 50ff352d6..3630df430 100644 --- a/src/qt/qt_vmmanager_serversocket.cpp +++ b/src/qt/qt_vmmanager_serversocket.cpp @@ -153,6 +153,16 @@ VMManagerServerSocket::jsonReceived(const QJsonObject &json) auto message_type = VMManagerProtocol::getClientMessageType(json); switch (message_type) { + case VMManagerProtocol::ClientMessage::WinIdMessage: + qDebug("WinId message received from client"); + params_object = VMManagerProtocol::getParams(json); + if (!params_object.isEmpty()) { + // valid object + if(params_object.value("params").type() == QJsonValue::Double) { + emit winIdReceived(params_object.value("params").toVariant().toULongLong()); + } + } + break; case VMManagerProtocol::ClientMessage::Status: qDebug("Status message received from client"); break; diff --git a/src/qt/qt_vmmanager_serversocket.hpp b/src/qt/qt_vmmanager_serversocket.hpp index 3e6e43a80..01c719813 100644 --- a/src/qt/qt_vmmanager_serversocket.hpp +++ b/src/qt/qt_vmmanager_serversocket.hpp @@ -75,6 +75,7 @@ signals: void dataReceived(); void windowStatusChanged(int status); void runningStatusChanged(VMManagerProtocol::RunningState state); + void winIdReceived(WId id); }; diff --git a/src/qt/qt_vmmanager_system.cpp b/src/qt/qt_vmmanager_system.cpp index 0a7382094..225b302df 100644 --- a/src/qt/qt_vmmanager_system.cpp +++ b/src/qt/qt_vmmanager_system.cpp @@ -15,6 +15,7 @@ * Copyright 2024 cold-brewed */ + #include #include #include @@ -26,10 +27,15 @@ #include #include #include +#include #include "qt_vmmanager_system.hpp" // #include "qt_vmmanager_details_section.hpp" #include "qt_vmmanager_detailsection.hpp" +#ifdef Q_OS_WINDOWS +#include +#endif + extern "C" { #include <86box/86box.h> @@ -427,12 +433,18 @@ VMManagerSystem::launchSettings() { // If the system is already running, instruct it to show settings if (process->processId() != 0) { +#ifdef Q_OS_WINDOWS + if (this->id) { + SetForegroundWindow((HWND)this->id); + } +#endif socket_server->serverSendMessage(VMManagerProtocol::ManagerMessage::ShowSettings); return; } // Otherwise, launch the system with the settings parameter setProcessEnvVars(); + window_obscured = true; QString program = main_binary.filePath(); QStringList open_command_args; QStringList args; @@ -776,6 +788,7 @@ VMManagerSystem::startServer() { connect(socket_server, &VMManagerServerSocket::dataReceived, this, &VMManagerSystem::dataReceived); connect(socket_server, &VMManagerServerSocket::windowStatusChanged, this, &VMManagerSystem::windowStatusChangeReceived); connect(socket_server, &VMManagerServerSocket::runningStatusChanged, this, &VMManagerSystem::runningStatusChangeReceived); + connect(socket_server, &VMManagerServerSocket::winIdReceived, this, [this] (WId id) { this->id = id; }); return true; } else { return false; @@ -846,6 +859,7 @@ VMManagerSystem::processStatusChanged() } } else if (process->state() == QProcess::ProcessState::NotRunning) { process_status = VMManagerSystem::ProcessStatus::Stopped; + window_obscured = false; } emit itemDataChanged(); emit clientProcessStatusChanged(); @@ -892,12 +906,20 @@ VMManagerSystem::runningStatusChangeReceived(VMManagerProtocol::RunningState sta { if(state == VMManagerProtocol::RunningState::Running) { process_status = VMManagerSystem::ProcessStatus::Running; + window_obscured = false; + windowStatusChanged(); } else if(state == VMManagerProtocol::RunningState::Paused) { process_status = VMManagerSystem::ProcessStatus::Paused; + window_obscured = false; + windowStatusChanged(); } else if(state == VMManagerProtocol::RunningState::RunningWaiting) { process_status = VMManagerSystem::ProcessStatus::RunningWaiting; + window_obscured = true; + windowStatusChanged(); } else if(state == VMManagerProtocol::RunningState::PausedWaiting) { process_status = VMManagerSystem::ProcessStatus::PausedWaiting; + window_obscured = true; + windowStatusChanged(); } else { process_status = VMManagerSystem::ProcessStatus::Unknown; } diff --git a/src/qt/qt_vmmanager_system.hpp b/src/qt/qt_vmmanager_system.hpp index 6ac0a7635..a73b31886 100644 --- a/src/qt/qt_vmmanager_system.hpp +++ b/src/qt/qt_vmmanager_system.hpp @@ -174,6 +174,8 @@ private: // Configuration file settings VMManagerConfig *config_settings; + WId id; + bool serverIsRunning; bool startServer(); diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index a62d71920..eca77d15d 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -6,15 +6,22 @@ * * This file is part of the 86Box distribution. * - * Windows raw input native filter for QT + * Windows raw input native filter for Qt * * * * Authors: Teemu Korhonen * Miran Grca, + * Sam Latinga + * Cacodemon345 * * Copyright 2021 Teemu Korhonen * Copyright 2016-2018 Miran Grca. + * Copyright 1997-2025 Sam Latinga + * Copyright 2024-2025 Cacodemon345. + * + * See this header for SDL3 code license: + * https://github.com/libsdl-org/SDL/blob/8e5fe0ea61dc87b29ca9a6119324221df0113bcf/src/video/windows/SDL_windowsrawinput.c#L1 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,6 +38,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/* Mouse RawInput code taken from SDL3. */ + #include "qt_winrawinputfilter.hpp" #include @@ -94,30 +103,158 @@ bool windows_is_light_theme() { return i == 1; } +struct +{ + HANDLE done_event = 0, ready_event = 0; + std::atomic_bool done{false}; + + size_t rawinput_offset = 0, rawinput_size = 0; + uint8_t* rawinput = nullptr; + + HANDLE thread = 0; +} win_rawinput_data; + +static void +win_poll_mouse(void) +{ + // Yes, this is a thing in C++. + auto* data = &win_rawinput_data; + uint32_t size, i, count, total = 0; + RAWINPUT *input; + //static int64_t ms_time = plat_get_ticks(); + + if (data->rawinput_offset == 0) { + BOOL isWow64; + + data->rawinput_offset = sizeof(RAWINPUTHEADER); + if (IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64) { + // We're going to get 64-bit data, so use the 64-bit RAWINPUTHEADER size + data->rawinput_offset += 8; + } + } + + input = (RAWINPUT *)data->rawinput; + for (;;) { + size = data->rawinput_size - (UINT)((BYTE *)input - data->rawinput); + count = GetRawInputBuffer(input, &size, sizeof(RAWINPUTHEADER)); + if (count == 0 || count == (UINT)-1) { + if (!data->rawinput || (count == (UINT)-1 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { + const UINT RAWINPUT_BUFFER_SIZE_INCREMENT = 96; // 2 64-bit raw mouse packets + BYTE *rawinput = (BYTE *)realloc(data->rawinput, data->rawinput_size + RAWINPUT_BUFFER_SIZE_INCREMENT); + if (!rawinput) { + break; + } + input = (RAWINPUT *)(rawinput + ((BYTE *)input - data->rawinput)); + data->rawinput = rawinput; + data->rawinput_size += RAWINPUT_BUFFER_SIZE_INCREMENT; + } else { + break; + } + } else { + total += count; + + // Advance input to the end of the buffer + while (count--) { + input = NEXTRAWINPUTBLOCK(input); + } + } + } + + if (total > 0) { + for (i = 0, input = (RAWINPUT *)data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) { + if (input->header.dwType == RIM_TYPEMOUSE) { + RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + data->rawinput_offset); + if (mouse_capture) + WindowsRawInputFilter::mouse_handle(rawmouse); + } + } + } + + //qDebug() << "Mouse delay: " << (plat_get_ticks() - ms_time); + //ms_time = plat_get_ticks(); +} + +static DWORD +win_rawinput_thread(void* param) +{ + RAWINPUTDEVICE rid = { + .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = 0, + .hwndTarget = nullptr + }; + auto window = CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); + if (!window) { + return 0; + } + + rid.hwndTarget = window; + if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) { + DestroyWindow(window); + return 0; + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + + SetEvent(win_rawinput_data.ready_event); + + while (!win_rawinput_data.done) { + DWORD result = MsgWaitForMultipleObjects(1, &win_rawinput_data.done_event, FALSE, INFINITE, QS_RAWINPUT); + + if (result != (WAIT_OBJECT_0 + 1)) { + break; + } + + // Clear the queue status so MsgWaitForMultipleObjects() will wait again + (void)GetQueueStatus(QS_RAWINPUT); + + win_poll_mouse(); + } + + rid.dwFlags |= RIDEV_REMOVE; + rid.hwndTarget = NULL; + + RegisterRawInputDevices(&rid, 1, sizeof(rid)); + DestroyWindow(window); + return 0; +} + extern "C" void win_joystick_handle(PRAWINPUT); std::unique_ptr WindowsRawInputFilter::Register(MainWindow *window) { - RAWINPUTDEVICE rid[2] = { + RAWINPUTDEVICE rid[1] = { { .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)) - return std::unique_ptr(nullptr); - else if (!hook_enabled && (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)) - return std::unique_ptr(nullptr); + if (!hook_enabled) { + RegisterRawInputDevices(rid, 1, sizeof(rid[0])); + } + win_rawinput_data.done_event = CreateEvent(nullptr, FALSE, FALSE, nullptr); + win_rawinput_data.ready_event = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + if (!win_rawinput_data.done_event || !win_rawinput_data.ready_event) { + warning("Failed to create RawInput events."); + + goto conclude; + } + + win_rawinput_data.thread = CreateThread(nullptr, 0, win_rawinput_thread, nullptr, 0, nullptr); + if (win_rawinput_data.thread) { + HANDLE handles[2] = { win_rawinput_data.ready_event, win_rawinput_data.thread }; + + WaitForMultipleObjects(2, handles, FALSE, INFINITE); + } else { + warning("Failed to create RawInput thread."); + } + +conclude: std::unique_ptr inputfilter(new WindowsRawInputFilter(window)); return inputfilter; @@ -135,25 +272,23 @@ WindowsRawInputFilter::WindowsRawInputFilter(MainWindow *window) WindowsRawInputFilter::~WindowsRawInputFilter() { - RAWINPUTDEVICE rid[2] = { + win_rawinput_data.done = true; + if (win_rawinput_data.done_event) + SetEvent(win_rawinput_data.done_event); + if (win_rawinput_data.thread) + WaitForSingleObject(win_rawinput_data.thread, INFINITE); + RAWINPUTDEVICE rid = { .usUsagePage = 0x01, .usUsage = 0x06, .dwFlags = RIDEV_REMOVE, .hwndTarget = NULL - }, - { - .usUsagePage = 0x01, - .usUsage = 0x02, - .dwFlags = RIDEV_REMOVE, - .hwndTarget = NULL - } - }; + }; - if (hook_enabled) - RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])); - else - RegisterRawInputDevices(rid, 2, sizeof(rid[0])); + if (!hook_enabled) + RegisterRawInputDevices(&rid, 1, sizeof(rid)); + + free(win_rawinput_data.rawinput); } static void @@ -305,10 +440,6 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input) case RIM_TYPEKEYBOARD: keyboard_handle(raw); break; - case RIM_TYPEMOUSE: - if (mouse_capture) - mouse_handle(raw); - break; case RIM_TYPEHID: win_joystick_handle(raw); break; @@ -328,9 +459,9 @@ WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) } void -WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) +WindowsRawInputFilter::mouse_handle(RAWMOUSE* raw) { - RAWMOUSE state = raw->data.mouse; + RAWMOUSE state = *raw; static int x, delta_x; static int y, delta_y; static int b, delta_z; diff --git a/src/qt/qt_winrawinputfilter.hpp b/src/qt/qt_winrawinputfilter.hpp index 411f7841c..9d8d6ba0e 100644 --- a/src/qt/qt_winrawinputfilter.hpp +++ b/src/qt/qt_winrawinputfilter.hpp @@ -38,6 +38,7 @@ #include #include +#include #include @@ -59,6 +60,8 @@ public: ~WindowsRawInputFilter(); + static void mouse_handle(RAWMOUSE* raw); + private: MainWindow *window; int buttons = 0; @@ -71,7 +74,6 @@ private: void handle_input(HRAWINPUT input); void keyboard_handle(PRAWINPUT raw); - void mouse_handle(PRAWINPUT raw); }; #endif diff --git a/src/qt/sdl_joystick.c b/src/qt/sdl_joystick.c index 83a2a67b1..ea3720eea 100644 --- a/src/qt/sdl_joystick.c +++ b/src/qt/sdl_joystick.c @@ -45,8 +45,10 @@ static SDL_Joystick *sdl_joy[MAX_PLAT_JOYSTICKS]; void joystick_init(void) { +#ifdef _WIN32 /* This is needed for SDL's Windows raw input backend to work properly without SDL video. */ SDL_SetHint(SDL_HINT_JOYSTICK_THREAD, "1"); +#endif if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0) { return; diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index 5173d4f05..ecd885d3a 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -222,6 +222,7 @@ joystick_get_capabilities(raw_joystick_t *rawjoy, plat_joystick_t *joy) UINT size = 0; PHIDP_BUTTON_CAPS btn_caps = NULL; PHIDP_VALUE_CAPS val_caps = NULL; + HIDP_CAPS caps; /* Get preparsed data (HID data format) */ GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, NULL, &size); @@ -229,7 +230,6 @@ joystick_get_capabilities(raw_joystick_t *rawjoy, plat_joystick_t *joy) if (GetRawInputDeviceInfoW(rawjoy->hdevice, RIDI_PREPARSEDDATA, rawjoy->data, &size) <= 0) fatal("joystick_get_capabilities: Failed to get preparsed data.\n"); - HIDP_CAPS caps; HidP_GetCaps(rawjoy->data, &caps); /* Buttons */ @@ -356,6 +356,7 @@ end_loop: free(info); } + free(deviceList); joystick_log("joystick_init: joysticks_present=%i\n", joysticks_present); /* Initialize the RawInput (joystick and gamepad) module. */ diff --git a/src/sio/sio_ali5123.c b/src/sio/sio_ali5123.c index 436e425d2..7dc522b30 100644 --- a/src/sio/sio_ali5123.c +++ b/src/sio/sio_ali5123.c @@ -81,28 +81,61 @@ ali5123_fdc_handler(ali5123_t *dev) static void ali5123_lpt_handler(ali5123_t *dev) { - uint16_t ld_port = 0; + uint16_t ld_port = 0x0000; + uint16_t mask = 0xfffc; 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]; + uint8_t lpt_mode = dev->ld_regs[3][0xf0] & 0x07; if (lpt_irq > 15) lpt_irq = 0xff; - if (lpt_dma == 4) + 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)); + lpt_set_fifo_threshold(0, (dev->ld_regs[3][0xf0] & 0x78) >> 3); + if ((lpt_mode == 0x04) && (dev->ld_regs[3][0xf1] & 0x80)) + lpt_mode = 0x00; + switch (lpt_mode) { + default: + case 0x04: + lpt_set_epp(0, 0); + lpt_set_ecp(0, 0); + lpt_set_ext(0, 0); + break; + case 0x00: + lpt_set_epp(0, 0); + lpt_set_ecp(0, 0); + lpt_set_ext(0, 1); + break; + case 0x01: case 0x05: + mask = 0xfff8; + lpt_set_epp(0, 1); + lpt_set_ecp(0, 0); + lpt_set_ext(0, 0); + break; + case 0x02: + lpt_set_epp(0, 0); + lpt_set_ecp(0, 1); + lpt_set_ext(0, 0); + break; + case 0x03: case 0x07: + mask = 0xfff8; + lpt_set_epp(0, 1); + lpt_set_ecp(0, 1); + lpt_set_ext(0, 0); + break; + } if (global_enable && local_enable) { - ld_port = make_port(dev, 3) & 0xFFFC; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) + ld_port = (make_port(dev, 3) & 0xfffc) & mask; + if ((ld_port >= 0x0100) && (ld_port <= (0x0ffc & mask))) lpt1_setup(ld_port); } lpt1_irq(lpt_irq); + lpt_port_dma(0, lpt_dma); } static void diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index e42c48ab4..5a0a8798a 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -123,6 +123,8 @@ lpt1_handler(pc87306_t *dev) uint8_t lpt_irq = LPT2_IRQ; uint8_t lpt_dma = ((dev->regs[0x18] & 0x06) >> 1); + lpt1_remove(); + if (lpt_dma == 0x00) lpt_dma = 0xff; @@ -157,17 +159,17 @@ lpt1_handler(pc87306_t *dev) if (dev->regs[0x1b] & 0x10) lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5; + lpt_set_ext(0, !!(dev->regs[0x02] & 0x80)); + + lpt_set_epp(0, !!(dev->regs[0x04] & 0x01)); + lpt_set_ecp(0, !!(dev->regs[0x04] & 0x04)); + if (lpt_port) 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 @@ -386,7 +388,7 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) if (valxor & 0x70) { lpt1_remove(); if (!(val & 0x40)) - dev->regs[0x19] = 0xEF; + dev->regs[0x19] = 0xef; if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 5044c6f54..80ce6781d 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -246,7 +246,7 @@ gus_midi_update_int_status(gus_t *gus) } void -writegus(uint16_t addr, uint8_t val, void *priv) +gus_write(uint16_t addr, uint8_t val, void *priv) { gus_t *gus = (gus_t *) priv; int c; @@ -703,7 +703,7 @@ writegus(uint16_t addr, uint8_t val, void *priv) } uint8_t -readgus(uint16_t addr, void *priv) +gus_read(uint16_t addr, void *priv) { gus_t *gus = (gus_t *) priv; uint8_t val = 0xff; @@ -1357,10 +1357,10 @@ gus_init(UNUSED(const device_t *info)) gus->base = device_get_config_hex16("base"); - io_sethandler(gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0100 + gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0506 + gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); - io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); + io_sethandler(gus->base, 0x0010, gus_read, NULL, NULL, gus_write, NULL, NULL, gus); + io_sethandler(0x0100 + gus->base, 0x0010, gus_read, NULL, NULL, gus_write, NULL, NULL, gus); + io_sethandler(0x0506 + gus->base, 0x0001, gus_read, NULL, NULL, gus_write, NULL, NULL, gus); + io_sethandler(0x0388, 0x0002, gus_read, NULL, NULL, gus_write, NULL, NULL, gus); if (gus->type == GUS_MAX) { ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 14726d358..4c73abf21 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1152,11 +1152,14 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) else if ((val & 0x06) == 0x02) mpu401_change_addr(sb->mpu, 0); } + sb->gameport_addr = 0; - gameport_remap(sb->gameport, 0); - if (!(val & 0x01)) { - sb->gameport_addr = 0x200; - gameport_remap(sb->gameport, 0x200); + if (sb->gameport != NULL) { + gameport_remap(sb->gameport, 0); + if (!(val & 0x01)) { + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, 0x200); + } } } break; @@ -1619,7 +1622,8 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) ess_fm_midi_write, NULL, NULL, ess); - gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200); + if (ess->gameport != NULL) + gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200); if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) { /* Not on ES1688. */ @@ -2864,11 +2868,17 @@ sb_init(UNUSED(const device_t *info)) sb_dsp_init(&sb->dsp, model, SB_SUBTYPE_DEFAULT, sb); sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); - sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); + sb_dsp_setdma8(&sb->dsp, 1); // SB 1, SB1.5 and 2 don't support DMA3 if (mixer_addr > 0x0000) sb_ct1335_mixer_reset(sb); + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } + /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { // TODO: See if this applies to the SB1.5 as well @@ -2948,6 +2958,12 @@ sb_mcv_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } + return sb; } @@ -3030,6 +3046,12 @@ sb_pro_v1_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } + return sb; } @@ -3084,6 +3106,12 @@ sb_pro_v2_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } + return sb; } @@ -3117,6 +3145,12 @@ sb_pro_mcv_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } + return sb; } @@ -3201,9 +3235,17 @@ sb_16_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - sb->gameport = gameport_add(&gameport_pnp_device); - sb->gameport_addr = 0x200; - gameport_remap(sb->gameport, sb->gameport_addr); + if (info->local == FM_YMF289B) { + sb->gameport = gameport_add(&gameport_pnp_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } else { + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } + } return sb; } @@ -3481,7 +3523,6 @@ sb_16_compat_init(const device_t *info) music_add_handler(sb_get_music_buffer_sb16_awe32, sb); sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); mpu401_init(sb->mpu, 0, 0, M_UART, (int) (intptr_t) info->local); sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3549,8 +3590,6 @@ sb_awe32_init(UNUSED(const device_t *info)) uint16_t emu_addr = device_get_config_hex16("emu_base"); int onboard_ram = device_get_config_int("onboard_ram"); - memset(sb, 0x00, sizeof(sb_t)); - sb->opl_enabled = device_get_config_int("opl"); if (sb->opl_enabled) fm_driver_get(FM_YMF262, &sb->opl); @@ -3594,7 +3633,6 @@ sb_awe32_init(UNUSED(const device_t *info)) if (mpu_addr) { sb->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART, device_get_config_int("receive_input401")); } else @@ -3606,9 +3644,11 @@ sb_awe32_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - sb->gameport = gameport_add(&gameport_pnp_device); - sb->gameport_addr = 0x200; - gameport_remap(sb->gameport, sb->gameport_addr); + if (device_get_config_int("gameport")) { + sb->gameport = gameport_add(&gameport_device); + sb->gameport_addr = 0x200; + gameport_remap(sb->gameport, sb->gameport_addr); + } return sb; } @@ -3870,9 +3910,11 @@ ess_x688_init(UNUSED(const device_t *info)) sb_dsp_set_mpu(&ess->dsp, ess->mpu); } - ess->gameport = gameport_add(&gameport_pnp_device); - ess->gameport_addr = 0x200; - gameport_remap(ess->gameport, ess->gameport_addr); + if (device_get_config_int("gameport")) { + ess->gameport = gameport_add(&gameport_device); + ess->gameport_addr = 0x200; + gameport_remap(ess->gameport, ess->gameport_addr); + } if (ide_base > 0x0000) { device_add(&ide_qua_pnp_device); @@ -4118,18 +4160,14 @@ static const device_config_t sb_config[] = { .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, .default_string = NULL, - .default_int = 1, + .default_int = 0, .file_filter = NULL, .spinner = { 0 }, - .selection = { - { .description = "DMA 1", .value = 1 }, - { .description = "DMA 3", .value = 3 }, - { .description = "" } - }, + .selection = { { 0 } }, .bios = { { 0 } } }, { @@ -4153,7 +4191,7 @@ static const device_config_t sb_config[] = { .spinner = { 0 }, .selection = { { 0 } }, .bios = { { 0 } } - }, + }, { .name = "", .description = "", .type = CONFIG_END } }; @@ -4178,8 +4216,8 @@ static const device_config_t sb15_config[] = { .bios = { { 0 } } }, { - .name = "irq", - .description = "IRQ", + .name = "irq", + .description = "IRQ", .type = CONFIG_SELECTION, .default_string = NULL, .default_int = 7, @@ -4195,18 +4233,14 @@ static const device_config_t sb15_config[] = { .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, .default_string = NULL, - .default_int = 1, + .default_int = 0, .file_filter = NULL, .spinner = { 0 }, - .selection = { - { .description = "DMA 1", .value = 1 }, - { .description = "DMA 3", .value = 3 }, - { .description = "" } - }, + .selection = { { 0 } }, .bios = { { 0 } } }, { @@ -4247,8 +4281,8 @@ static const device_config_t sb15_config[] = { static const device_config_t sb2_config[] = { { - .name = "base", - .description = "Address", + .name = "base", + .description = "Address", .type = CONFIG_HEX16, .default_string = NULL, .default_int = 0x220, @@ -4295,18 +4329,14 @@ static const device_config_t sb2_config[] = { .bios = { { 0 } } }, { - .name = "dma", - .description = "DMA", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 1, + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, .file_filter = NULL, .spinner = { 0 }, - .selection = { - { .description = "DMA 1", .value = 1 }, - { .description = "DMA 3", .value = 3 }, - { .description = "" } - }, + .selection = { { 0 } }, .bios = { { 0 } } }, { @@ -4367,7 +4397,7 @@ static const device_config_t sb_mcv_config[] = { .name = "dma", .description = "DMA", .type = CONFIG_SELECTION, - .default_string = "", + .default_string = NULL, .default_int = 1, .file_filter = NULL, .spinner = { 0 }, @@ -4378,6 +4408,17 @@ static const device_config_t sb_mcv_config[] = { }, .bios = { { 0 } } }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "opl", .description = "Enable OPL", @@ -4452,6 +4493,17 @@ static const device_config_t sb_pro_config[] = { }, .bios = { { 0 } } }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "opl", .description = "Enable OPL", @@ -4478,6 +4530,17 @@ static const device_config_t sb_pro_config[] = { }; static const device_config_t sb_pro_mcv_config[] = { + { + .name = "gameport", + .description = "Enable Game port", + .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", @@ -4575,6 +4638,17 @@ static const device_config_t sb_16_config[] = { }, .bios = { { 0 } } }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "opl", .description = "Enable OPL", @@ -4857,6 +4931,17 @@ static const device_config_t sb_awe32_config[] = { }, .bios = { { 0 } } }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "opl", .description = "Enable OPL", @@ -5186,6 +5271,17 @@ static const device_config_t ess_688_config[] = { }, .bios = { { 0 } } }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "ide_ctrl", .description = "IDE Controller", @@ -5269,6 +5365,17 @@ static const device_config_t ess_1688_config[] = { }, .bios = { { 0 } } }, + { + .name = "gameport", + .description = "Enable Game port", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "ide_ctrl", .description = "IDE Controller", @@ -5343,7 +5450,7 @@ static const device_config_t ess_1688_pnp_config[] = { .name = "control_pc_speaker", .description = "Control PC speaker", .type = CONFIG_BINARY, - .default_string = "", + .default_string = NULL, .default_int = 0, .file_filter = NULL, .spinner = { 0 }, @@ -5354,7 +5461,7 @@ static const device_config_t ess_1688_pnp_config[] = { .name = "receive_input", .description = "Receive MIDI input", .type = CONFIG_BINARY, - .default_string = "", + .default_string = NULL, .default_int = 1, .file_filter = NULL, .spinner = { 0 }, @@ -5365,7 +5472,7 @@ static const device_config_t ess_1688_pnp_config[] = { .name = "receive_input401", .description = "Receive MIDI input (MPU-401)", .type = CONFIG_BINARY, - .default_string = "", + .default_string = NULL, .default_int = 0, .file_filter = NULL, .spinner = { 0 }, diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 10e5601f4..76956c417 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -1582,19 +1582,19 @@ sb_exec_command(sb_dsp_t *dsp) timer_set_delay_u64(&dsp->output_timer, (uint64_t) trunc(dsp->sblatcho)); break; case 0x90: /* High speed 8-bit autoinit DMA output */ - if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated + if (dsp->sb_type >= SB_DSP_201) // TODO docs need validated sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x91: /* High speed 8-bit single cycle DMA output */ - if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated + if (dsp->sb_type >= SB_DSP_201) // TODO docs need validated sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0x98: /* High speed 8-bit autoinit DMA input */ - if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated + if (dsp->sb_type >= SB_DSP_201) // TODO docs need validated sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x99: /* High speed 8-bit single cycle DMA input */ - if ((dsp->sb_type >= SB_DSP_201) && (dsp->sb_type < SB16_DSP_404)) // TODO docs need validated + if (dsp->sb_type >= SB_DSP_201) // TODO docs need validated sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0xA0: /* Set input mode to mono */ diff --git a/src/sound/snd_speaker.c b/src/sound/snd_speaker.c index 0537cd09a..063554875 100644 --- a/src/sound/snd_speaker.c +++ b/src/sound/snd_speaker.c @@ -56,7 +56,7 @@ speaker_update(void) int32_t val; double amplitude; - amplitude = ((speaker_count / 64.0) * 10240.0) - 5120.0; + amplitude = ((speaker_count / 256.0) * 10240.0) - 5120.0; if (amplitude > 5120.0) amplitude = 5120.0; diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index 9cc41c504..b832cb526 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -157,14 +157,13 @@ static const device_config_t ssi2001_config[] = { .description = "Enable Game port", .type = CONFIG_BINARY, .default_string = NULL, - .default_int = 1, + .default_int = 0, .file_filter = NULL, .spinner = { 0 }, .selection = { { 0 } }, .bios = { { 0 } } }, - - { + { .name = "sid_config", .description = "SID Model", .type = CONFIG_HEX16, @@ -201,7 +200,7 @@ static const device_config_t entertainer_config[] = { .description = "Enable Game port", .type = CONFIG_BINARY, .default_string = NULL, - .default_int = 1, + .default_int = 0, .file_filter = NULL, .spinner = { 0 }, .selection = { { 0 } }, diff --git a/src/sound/ymfm/ymfm_opl.h b/src/sound/ymfm/ymfm_opl.h index 843e5b274..71b098e97 100644 --- a/src/sound/ymfm/ymfm_opl.h +++ b/src/sound/ymfm/ymfm_opl.h @@ -52,7 +52,7 @@ namespace ymfm // // System-wide registers: // 01 xxxxxxxx Test register -// --x----- Enable OPL compatibility mode [OPL2 only] (1 = enable) +// --x----- Enable OPL compatibility mode [OPL2 only] (0 = enable) // 02 xxxxxxxx Timer A value (4 * OPN) // 03 xxxxxxxx Timer B value // 04 x------- RST @@ -243,7 +243,7 @@ public: uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0x60, 0, 4, opoffs); } uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0x80, 4, 4, opoffs); } uint32_t op_release_rate(uint32_t opoffs) const { return byte(0x80, 0, 4, opoffs); } - uint32_t op_waveform(uint32_t opoffs) const { return IsOpl2Plus ? byte(0xe0, 0, newflag() ? 3 : 2, opoffs) : 0; } + uint32_t op_waveform(uint32_t opoffs) const { return waveform_enable() ? byte(0xe0, 0, newflag() ? 3 : 2, opoffs) : 0; } protected: // return a bitfield extracted from a byte diff --git a/src/sound/ymfm/ymfm_opn.cpp b/src/sound/ymfm/ymfm_opn.cpp index 16ca3416c..60469e1c0 100644 --- a/src/sound/ymfm/ymfm_opn.cpp +++ b/src/sound/ymfm/ymfm_opn.cpp @@ -155,14 +155,13 @@ bool opn_registers_base::write(uint16_t index, uint8_t data, uint32_t &c // writes to the upper half just latch (only low 6 bits matter) if (bitfield(index, 2)) - m_regdata[latchindex] = data | 0x80; + m_regdata[latchindex] = data & 0x3f; - // writes to the lower half only commit if the latch is there - else if (bitfield(m_regdata[latchindex], 7)) + // writes to the lower half also apply said latch + else { m_regdata[index] = data; - m_regdata[index | 4] = m_regdata[latchindex] & 0x3f; - m_regdata[latchindex] = 0; + m_regdata[index | 4] = m_regdata[latchindex]; } return false; } diff --git a/src/unix/gamemode/gamemode_client.h b/src/unix/gamemode/gamemode_client.h new file mode 100644 index 000000000..49c34fb9f --- /dev/null +++ b/src/unix/gamemode/gamemode_client.h @@ -0,0 +1,376 @@ +/* + +Copyright (c) 2017-2025, Feral Interactive and the GameMode contributors +All rights reserved. + +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 Feral Interactive 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. + + */ +#ifndef CLIENT_GAMEMODE_H +#define CLIENT_GAMEMODE_H +/* + * GameMode supports the following client functions + * Requests are refcounted in the daemon + * + * int gamemode_request_start() - Request gamemode starts + * 0 if the request was sent successfully + * -1 if the request failed + * + * int gamemode_request_end() - Request gamemode ends + * 0 if the request was sent successfully + * -1 if the request failed + * + * GAMEMODE_AUTO can be defined to make the above two functions apply during static init and + * destruction, as appropriate. In this configuration, errors will be printed to stderr + * + * int gamemode_query_status() - Query the current status of gamemode + * 0 if gamemode is inactive + * 1 if gamemode is active + * 2 if gamemode is active and this client is registered + * -1 if the query failed + * + * int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process + * 0 if the request was sent successfully + * -1 if the request failed + * -2 if the request was rejected + * + * int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process + * 0 if the request was sent successfully + * -1 if the request failed + * -2 if the request was rejected + * + * int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process + * 0 if gamemode is inactive + * 1 if gamemode is active + * 2 if gamemode is active and this client is registered + * -1 if the query failed + * + * const char* gamemode_error_string() - Get an error string + * returns a string describing any of the above errors + * + * Note: All the above requests can be blocking - dbus requests can and will block while the daemon + * handles the request. It is not recommended to make these calls in performance critical code + */ + +#include +#include + +#include +#include + +#include + +#include + +static char internal_gamemode_client_error_string[512] = { 0 }; + +/** + * Load libgamemode dynamically to dislodge us from most dependencies. + * This allows clients to link and/or use this regardless of runtime. + * See SDL2 for an example of the reasoning behind this in terms of + * dynamic versioning as well. + */ +static volatile int internal_libgamemode_loaded = 1; + +/* Typedefs for the functions to load */ +typedef int (*api_call_return_int)(void); +typedef const char *(*api_call_return_cstring)(void); +typedef int (*api_call_pid_return_int)(pid_t); + +/* Storage for functors */ +static api_call_return_int REAL_internal_gamemode_request_start = NULL; +static api_call_return_int REAL_internal_gamemode_request_end = NULL; +static api_call_return_int REAL_internal_gamemode_query_status = NULL; +static api_call_return_cstring REAL_internal_gamemode_error_string = NULL; +static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL; +static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL; +static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL; + +/** + * Internal helper to perform the symbol binding safely. + * + * Returns 0 on success and -1 on failure + */ +__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol( + void *handle, const char *name, void **out_func, size_t func_size, bool required) +{ + void *symbol_lookup = NULL; + char *dl_error = NULL; + + /* Safely look up the symbol */ + symbol_lookup = dlsym(handle, name); + dl_error = dlerror(); + if (required && (dl_error || !symbol_lookup)) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "dlsym failed - %s", + dl_error); + return -1; + } + + /* Have the symbol correctly, copy it to make it usable */ + memcpy(out_func, &symbol_lookup, func_size); + return 0; +} + +/** + * Loads libgamemode and needed functions + * + * Returns 0 on success and -1 on failure + */ +__attribute__((always_inline)) static inline int internal_load_libgamemode(void) +{ + /* We start at 1, 0 is a success and -1 is a fail */ + if (internal_libgamemode_loaded != 1) { + return internal_libgamemode_loaded; + } + + /* Anonymous struct type to define our bindings */ + struct binding { + const char *name; + void **functor; + size_t func_size; + bool required; + } bindings[] = { + { "real_gamemode_request_start", + (void **)&REAL_internal_gamemode_request_start, + sizeof(REAL_internal_gamemode_request_start), + true }, + { "real_gamemode_request_end", + (void **)&REAL_internal_gamemode_request_end, + sizeof(REAL_internal_gamemode_request_end), + true }, + { "real_gamemode_query_status", + (void **)&REAL_internal_gamemode_query_status, + sizeof(REAL_internal_gamemode_query_status), + false }, + { "real_gamemode_error_string", + (void **)&REAL_internal_gamemode_error_string, + sizeof(REAL_internal_gamemode_error_string), + true }, + { "real_gamemode_request_start_for", + (void **)&REAL_internal_gamemode_request_start_for, + sizeof(REAL_internal_gamemode_request_start_for), + false }, + { "real_gamemode_request_end_for", + (void **)&REAL_internal_gamemode_request_end_for, + sizeof(REAL_internal_gamemode_request_end_for), + false }, + { "real_gamemode_query_status_for", + (void **)&REAL_internal_gamemode_query_status_for, + sizeof(REAL_internal_gamemode_query_status_for), + false }, + }; + + void *libgamemode = NULL; + + /* Try and load libgamemode */ + libgamemode = dlopen("libgamemode.so.0", RTLD_NOW); + if (!libgamemode) { + /* Attempt to load unversioned library for compatibility with older + * versions (as of writing, there are no ABI changes between the two - + * this may need to change if ever ABI-breaking changes are made) */ + libgamemode = dlopen("libgamemode.so", RTLD_NOW); + if (!libgamemode) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "dlopen failed - %s", + dlerror()); + internal_libgamemode_loaded = -1; + return -1; + } + } + + /* Attempt to bind all symbols */ + for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) { + struct binding *binder = &bindings[i]; + + if (internal_bind_libgamemode_symbol(libgamemode, + binder->name, + binder->functor, + binder->func_size, + binder->required)) { + internal_libgamemode_loaded = -1; + return -1; + }; + } + + /* Success */ + internal_libgamemode_loaded = 0; + return 0; +} + +/** + * Redirect to the real libgamemode + */ +__attribute__((always_inline)) static inline const char *gamemode_error_string(void) +{ + /* If we fail to load the system gamemode, or we have an error string already, return our error + * string instead of diverting to the system version */ + if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') { + return internal_gamemode_client_error_string; + } + + /* Assert for static analyser that the function is not NULL */ + assert(REAL_internal_gamemode_error_string != NULL); + + return REAL_internal_gamemode_error_string(); +} + +/** + * Redirect to the real libgamemode + * Allow automatically requesting game mode + * Also prints errors as they happen. + */ +#ifdef GAMEMODE_AUTO +__attribute__((constructor)) +#else +__attribute__((always_inline)) static inline +#endif +int gamemode_request_start(void) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + /* Assert for static analyser that the function is not NULL */ + assert(REAL_internal_gamemode_request_start != NULL); + + if (REAL_internal_gamemode_request_start() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + return 0; +} + +/* Redirect to the real libgamemode */ +#ifdef GAMEMODE_AUTO +__attribute__((destructor)) +#else +__attribute__((always_inline)) static inline +#endif +int gamemode_request_end(void) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + /* Assert for static analyser that the function is not NULL */ + assert(REAL_internal_gamemode_request_end != NULL); + + if (REAL_internal_gamemode_request_end() < 0) { +#ifdef GAMEMODE_AUTO + fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string()); +#endif + return -1; + } + + return 0; +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_query_status(void) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_query_status == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_query_status missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_query_status(); +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_request_start_for == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_request_start_for missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_request_start_for(pid); +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_request_end_for == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_request_end_for missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_request_end_for(pid); +} + +/* Redirect to the real libgamemode */ +__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid) +{ + /* Need to load gamemode */ + if (internal_load_libgamemode() < 0) { + return -1; + } + + if (REAL_internal_gamemode_query_status_for == NULL) { + snprintf(internal_gamemode_client_error_string, + sizeof(internal_gamemode_client_error_string), + "gamemode_query_status_for missing (older host?)"); + return -1; + } + + return REAL_internal_gamemode_query_status_for(pid); +} + +#endif // CLIENT_GAMEMODE_H diff --git a/src/unix/unix.c b/src/unix/unix.c index 2bbbda067..f3580cd19 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -576,7 +576,7 @@ main_thread(UNUSED(void *param)) old_time = new_time; if (drawits > 0 && !dopause) { /* Yes, so do one frame now. */ - drawits -= 10; + drawits -= force_10ms ? 10 : 1; if (drawits > 50) drawits = 0; @@ -584,7 +584,7 @@ main_thread(UNUSED(void *param)) pc_run(); /* Every 200 frames we save the machine status. */ - if (++frames >= 200 && nvr_dosave) { + if (++frames >= (force_10ms ? 200 : 2000) && nvr_dosave) { nvr_save(); nvr_dosave = 0; frames = 0; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index df8965caf..4bb678857 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -270,7 +270,7 @@ mach_log(const char *fmt, ...) static int mach_pixel_write(mach_t *mach) { - if (mach->accel.dp_config & 1) + if (mach->accel.dp_config & 0x01) return 1; return 0; @@ -279,7 +279,7 @@ mach_pixel_write(mach_t *mach) static int mach_pixel_read(mach_t *mach) { - if (mach->accel.dp_config & 1) + if (mach->accel.dp_config & 0x01) return 0; return 1; @@ -4303,6 +4303,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in dev->force_busy = 0; else if ((mono_src == 2) || (frgd_sel == 2) || (bkgd_sel == 2)) dev->force_busy = 0; + else if (!dev->accel.cmd_back) + dev->force_busy = 0; + + mach_log("2Force Busy=%d, frgdsel=%d, bkgdsel=%d, monosrc=%d, read=%d, dpconfig=%04x, back=%d.\n", dev->force_busy, frgd_sel, bkgd_sel, mono_src, mach_pixel_read(mach), mach->accel.dp_config, dev->accel.cmd_back); break; case 5: if (dev->accel.sx >= mach->accel.width) diff --git a/src/video/vid_cga_quadcolor.c b/src/video/vid_cga_quadcolor.c index 5974682c8..642391679 100644 --- a/src/video/vid_cga_quadcolor.c +++ b/src/video/vid_cga_quadcolor.c @@ -155,7 +155,13 @@ quadcolor_out(uint16_t addr, uint8_t val, void *priv) case 0x3de: /* NOTE: the polarity of this register is the opposite of what the manual says */ if (quadcolor->has_quadcolor_2) - quadcolor->quadcolor_2_oe = !(val & 0x10); + /* + NOTE: PC Paintbrush writes FF and then gets stuck if it doesn't get enabled, + and then it expects to disable it with 0x00. The only way to square this + with the inverted polarity note above is if that was a value other than + 0x00 with bit 4 clear. + */ + quadcolor->quadcolor_2_oe = ((!(val & 0x10)) || (val == 0xff)) && (val != 0x00); return; default: @@ -290,22 +296,15 @@ quadcolor_render(quadcolor_t *quadcolor, int line) int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS); - if (((quadcolor->cgamode & highres_graphics_flag) == highres_graphics_flag)) { - for (column = 0; column < 8; ++column) { - buffer32->line[line][column] = 0; - if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES) - buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 8] = (quadcolor->quadcolor_ctrl & 15); /* TODO: Is Quadcolor bg color actually relevant, here? */ - else - buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 8] = (quadcolor->quadcolor_ctrl & 15); /* TODO: Is Quadcolor bg color actually relevant, here? */ - } - } else { - for (column = 0; column < 8; ++column) { - buffer32->line[line][column] = (quadcolor->cgacol & 15) + 16; - if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES) - buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 8] = (quadcolor->cgacol & 15) + 16; - else - buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 8] = (quadcolor->cgacol & 15) + 16; - } + cols[0] = ((quadcolor->cgamode & highres_graphics_flag) == highres_graphics_flag) ? (quadcolor->quadcolor_ctrl & 15) : + (quadcolor->cgacol & 15); + + for (column = 0; column < 8; ++column) { + buffer32->line[line][column] = cols[0]; + if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES) + buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 3) + 8] = cols[0]; + else + buffer32->line[line][column + (quadcolor->crtc[CGA_CRTC_HDISP] << 4) + 8] = cols[0]; } if (quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES) { /* 80-column text */ for (x = 0; x < quadcolor->crtc[CGA_CRTC_HDISP]; x++) { @@ -322,20 +321,24 @@ quadcolor_render(quadcolor_t *quadcolor, int line) cols[1] = cols[0]; } else cols[0] = (attr >> 4) + 16; + uint8_t charline = quadcolor->scanline & 7; if (drawcursor) { for (column = 0; column < 8; column++) { - buffer32->line[line][(x << 3) + column + 8] - = (cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15) | get_next_qc2_pixel(quadcolor); + dat = (cols[(fontdat[chr + quadcolor->fontbase][charline] & (1 << (column ^ 7))) ? 1 : 0] ^ 15); + buffer32->line[line][(x << 3) + column + 8] = + dat | get_next_qc2_pixel(quadcolor); } } else { for (column = 0; column < 8; column++) { - buffer32->line[line][(x << 3) + column + 8] - = cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] | get_next_qc2_pixel(quadcolor); + dat = cols[(fontdat[chr + quadcolor->fontbase][charline] & (1 << (column ^ 7))) ? 1 : 0]; + buffer32->line[line][(x << 3) + column + 8] = + dat | get_next_qc2_pixel(quadcolor); } } quadcolor->memaddr++; } - } else if (!(quadcolor->cgamode & CGA_MODE_FLAG_GRAPHICS)) { /* not graphics (nor 80-column text) => 40-column text */ + } else if (!(quadcolor->cgamode & CGA_MODE_FLAG_GRAPHICS)) { + /* Not graphics (nor 80-column text) => 40-column text. */ for (x = 0; x < quadcolor->crtc[CGA_CRTC_HDISP]; x++) { if (quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) { chr = quadcolor->vram[(quadcolor->page_offset ^ (quadcolor->memaddr << 1)) & DEVICE_VRAM_MASK]; @@ -351,23 +354,27 @@ quadcolor_render(quadcolor_t *quadcolor, int line) } else cols[0] = (attr >> 4) + 16; quadcolor->memaddr++; + uint8_t charline = quadcolor->scanline & 7; if (drawcursor) { for (column = 0; column < 8; column++) { - dat = (cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15); - buffer32->line[line][(x << 4) + (column << 1) + 8] = dat | get_next_qc2_pixel(quadcolor); - buffer32->line[line][(x << 4) + (column << 1) + 9] = dat | get_next_qc2_pixel(quadcolor); - + dat = (cols[(fontdat[chr + quadcolor->fontbase][charline] & (1 << (column ^ 7))) ? 1 : 0] ^ 15); + buffer32->line[line][(x << 4) + (column << 1) + 8] = + dat | get_next_qc2_pixel(quadcolor); + buffer32->line[line][(x << 4) + (column << 1) + 9] = + dat | get_next_qc2_pixel(quadcolor); } } else { for (column = 0; column < 8; column++) { - dat = cols[(fontdat[chr + quadcolor->fontbase][quadcolor->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0]; - buffer32->line[line][(x << 4) + (column << 1) + 8] = dat | get_next_qc2_pixel(quadcolor); - buffer32->line[line][(x << 4) + (column << 1) + 9] = dat | get_next_qc2_pixel(quadcolor); - + dat = cols[(fontdat[chr + quadcolor->fontbase][charline] & (1 << (column ^ 7))) ? 1 : 0]; + buffer32->line[line][(x << 4) + (column << 1) + 8] = + dat | get_next_qc2_pixel(quadcolor); + buffer32->line[line][(x << 4) + (column << 1) + 9] = + dat | get_next_qc2_pixel(quadcolor); } } } - } else if (!(quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { /* not hi-res (but graphics) => 4-color mode */ + } else if (!(quadcolor->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) { + /* Not hi-res (but graphics) => 4-color mode. */ cols[0] = (quadcolor->cgacol & 15) | 16; col = (quadcolor->cgacol & 16) ? 24 : 16; if (quadcolor->cgamode & CGA_MODE_FLAG_BW) { @@ -385,8 +392,10 @@ quadcolor_render(quadcolor_t *quadcolor, int line) } for (x = 0; x < quadcolor->crtc[CGA_CRTC_HDISP]; x++) { if (quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) - dat = (quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000))] << 8) | - quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000) + 1)]; + dat = (quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + + ((quadcolor->scanline & 1) * 0x2000))] << 8) | + quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + + ((quadcolor->scanline & 1) * 0x2000) + 1)]; else dat = 0; quadcolor->memaddr++; @@ -396,15 +405,20 @@ quadcolor_render(quadcolor_t *quadcolor, int line) dat <<= 2; } } - } else { /* 2-color hi-res graphics mode */ - cols[0] = quadcolor->quadcolor_ctrl & 15; /* background color (Quadcolor-specific) */; + } else { + /* 2-color hi-res graphics mode. */ + /* Background color (Quadcolor-specific). */ + cols[0] = quadcolor->quadcolor_ctrl & 15; cols[1] = (quadcolor->cgacol & 15) + 16; for (x = 0; x < quadcolor->crtc[CGA_CRTC_HDISP]; x++) { if (quadcolor->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) /* video enabled */ - dat = (quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000))] << 8) | - quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + ((quadcolor->scanline & 1) * 0x2000) + 1)]; + dat = (quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + + ((quadcolor->scanline & 1) * 0x2000))] << 8) | + quadcolor->vram[quadcolor->page_offset ^ (((quadcolor->memaddr << 1) & 0x1fff) + + ((quadcolor->scanline & 1) * 0x2000) + 1)]; else - dat = quadcolor->quadcolor_ctrl & 15; /* TODO: Is Quadcolor bg color actually relevant, here? Probably. See QC2 manual p.46 1. */; + /* TODO: Is Quadcolor bg color actually relevant, here? Probably. See QC2 manual p.46 1. */ + dat = quadcolor->quadcolor_ctrl & 15; quadcolor->memaddr++; for (column = 0; column < 16; column++) { buffer32->line[line][(x << 4) + column + 8] = cols[dat >> 15] | get_next_qc2_pixel(quadcolor); diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 21671f4b3..26bb38991 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -1895,7 +1895,7 @@ const device_t cpqega_device = { }; const device_t sega_device = { - .name = "SuperEGA", + .name = "Chips & Technologies SuperEGA", .internal_name = "superega", .flags = DEVICE_ISA, .local = EGA_SUPEREGA, diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index a9b0c65a5..c3534f7bc 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -33,6 +33,14 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#define VAR_BYTE_MODE (0 << 0) +#define VAR_WORD_MODE_MA13 (1 << 0) +#define VAR_WORD_MODE_MA15 (2 << 0) +#define VAR_DWORD_MODE (3 << 0) +#define VAR_MODE_MASK (3 << 0) +#define VAR_ROW0_MA13 (1 << 2) +#define VAR_ROW1_MA14 (1 << 3) + typedef struct paradise_t { svga_t svga; @@ -77,6 +85,7 @@ paradise_in(uint16_t addr, void *priv) { paradise_t *paradise = (paradise_t *) priv; svga_t *svga = ¶dise->svga; + uint8_t max_sr = (paradise->type >= WD90C30) ? 0x15 : 0x12; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -86,7 +95,7 @@ paradise_in(uint16_t addr, void *priv) if (svga->seqaddr > 7) { if (paradise->type < WD90C11 || svga->seqregs[6] != 0x48) return 0xff; - if (svga->seqaddr > 0x12) + if (svga->seqaddr > max_sr) return 0xff; return svga->seqregs[svga->seqaddr & 0x1f]; } @@ -212,6 +221,20 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) else svga->gdcreg[0x0b] |= 0x40; + if (svga->crtc[0x2f] & 0x02) + svga->decode_mask = 0x3ffff; + else switch (svga->gdcreg[0x0b] & 0xc0) { + case 0x00: case 0x40: + svga->decode_mask = 0x3ffff; + break; + case 0x80: + svga->decode_mask = 0x7ffff; + break; + case 0xc0: + svga->decode_mask = 0xfffff; + break; + } + paradise_remap(paradise); return; case 0x0e: @@ -243,6 +266,21 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) if (old != val) { if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { + if (svga->crtcreg == 0x2f) { + if (svga->crtc[0x2f] & 0x02) + svga->decode_mask = 0x3ffff; + else switch (svga->gdcreg[0x0b] & 0xc0) { + case 0x00: case 0x40: + svga->decode_mask = 0x3ffff; + break; + case 0x80: + svga->decode_mask = 0x7ffff; + break; + case 0xc0: + svga->decode_mask = 0xfffff; + break; + } + } if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); @@ -267,30 +305,92 @@ paradise_remap(paradise_t *paradise) svga_t *svga = ¶dise->svga; if (svga->seqregs[0x11] & 0x80) { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[0x0a] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } else if (svga->gdcreg[0x0b] & 0x08) { - if (svga->gdcreg[6] & 0x0c) { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[0x0a] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } else { - paradise->read_bank[0] = paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; - paradise->read_bank[1] = paradise->write_bank[1] = (svga->gdcreg[0xa] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->read_bank[2] = paradise->write_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[3] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } - } else { - paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; - paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - paradise->write_bank[0] = paradise->write_bank[2] = svga->gdcreg[9] << 12; - paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); - } + paradise->read_bank[0] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[0] + 0x8000; - /*There are separate drivers for 1M and 512K/256K versions of the PVGA chips.*/ + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[0] + 0x8000; + + if ((svga->gdcreg[6] & 0x0c) == 0x00) { + paradise->read_bank[2] = paradise->read_bank[1] + 0x8000; + paradise->read_bank[3] = paradise->read_bank[2] + 0x8000; + + paradise->write_bank[2] = paradise->write_bank[1] + 0x8000; + paradise->write_bank[3] = paradise->write_bank[2] + 0x8000; + } else { + if (svga->gdcreg[6] & 0x08) { + paradise->read_bank[1] = paradise->read_bank[0]; + + paradise->write_bank[1] = paradise->write_bank[0]; + } + + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[1]; + + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[1]; + } + } else if (svga->gdcreg[0x0b] & 0x08) { + if ((svga->gdcreg[6] & 0x0c) == 0x00) { + paradise->read_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->read_bank[0] + 0x8000; + paradise->read_bank[2] = svga->gdcreg[9] << 12; + paradise->read_bank[3] = paradise->read_bank[2] + 0x8000; + + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[0] + 0x8000; + paradise->write_bank[2] = svga->gdcreg[9] << 12; + paradise->write_bank[3] = paradise->write_bank[2] + 0x8000; + } else if ((svga->gdcreg[6] & 0x0c) == 0x04) { + paradise->read_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = svga->gdcreg[9] << 12; + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[1]; + + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = svga->gdcreg[9] << 12; + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[1]; + } else { + paradise->read_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->read_bank[1] = paradise->read_bank[0]; + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[0]; + + paradise->write_bank[0] = svga->gdcreg[0x0a] << 12; + paradise->write_bank[1] = paradise->write_bank[0]; + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[0]; + } + } else { + paradise->read_bank[0] = svga->gdcreg[9] << 12; + paradise->read_bank[1] = paradise->read_bank[0] + 0x8000; + + paradise->write_bank[0] = svga->gdcreg[9] << 12; + paradise->write_bank[1] = paradise->write_bank[0] + 0x8000; + + if ((svga->gdcreg[6] & 0x0c) == 0x00) { + paradise->read_bank[2] = paradise->read_bank[1] + 0x8000; + paradise->read_bank[3] = paradise->read_bank[2] + 0x8000; + + paradise->write_bank[2] = paradise->write_bank[1] + 0x8000; + paradise->write_bank[3] = paradise->write_bank[2] + 0x8000; + } else { + if (svga->gdcreg[6] & 0x08) { + paradise->read_bank[1] = paradise->read_bank[0]; + + paradise->write_bank[1] = paradise->write_bank[0]; + } + + paradise->read_bank[2] = paradise->read_bank[0]; + paradise->read_bank[3] = paradise->read_bank[1]; + + paradise->write_bank[2] = paradise->write_bank[0]; + paradise->write_bank[3] = paradise->write_bank[1]; + } + } + + /* There are separate drivers for 1M and 512K/256K versions of the PVGA chips. */ if ((svga->gdcreg[0x0b] & 0xc0) < 0xc0) { paradise->read_bank[1] &= 0x7ffff; paradise->write_bank[1] &= 0x7ffff; @@ -300,6 +400,85 @@ paradise_remap(paradise_t *paradise) } } +void +paradise_render_4bpp_word_highres(svga_t *svga) +{ + int x; + int oddeven; + uint32_t addr; + uint32_t *p; + uint8_t edat[4]; + uint8_t dat; + uint32_t changed_addr; + + if ((svga->displine + svga->y_add) < 0) + return; + + changed_addr = ((svga->memaddr & 0x3fffc) << 1); + + 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]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = ((svga->memaddr & 0x3fffc) << 1); + oddeven = 0; + + oddeven = (svga->memaddr & 2) ? 1 : 0; + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&svga->vram[addr | oddeven]) & 0x00ff00ff; + svga->memaddr = (svga->memaddr + 2) & 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]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | + (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | + (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + + p += 8; + } + } +} + +static int +paradise_mode_is_word(svga_t *svga) +{ + int func_nr; + + if (svga->fb_only) + func_nr = 0; + else { + if (svga->force_dword_mode) + func_nr = VAR_DWORD_MODE; + else if (svga->crtc[0x14] & 0x40) + func_nr = svga->packed_chain4 ? VAR_BYTE_MODE : VAR_DWORD_MODE; + else if (svga->crtc[0x17] & 0x40) + func_nr = VAR_BYTE_MODE; + else if (svga->crtc[0x17] & 0x20) + func_nr = VAR_WORD_MODE_MA15; + else + func_nr = VAR_WORD_MODE_MA13; + + if (!(svga->crtc[0x17] & 0x01)) + func_nr |= VAR_ROW0_MA13; + if (!(svga->crtc[0x17] & 0x02)) + func_nr |= VAR_ROW1_MA14; + } + + return (func_nr == 2); +} + void paradise_recalctimings(svga_t *svga) { @@ -318,17 +497,30 @@ paradise_recalctimings(svga_t *svga) svga->vblankstart |= 0x400; if (svga->crtc[0x3e] & 0x10) svga->split |= 0x400; - - svga->interlace = !!(svga->crtc[0x2d] & 0x20); } + if (paradise->type >= WD90C11) + svga->interlace = !!(svga->crtc[0x2d] & 0x20); + if (paradise->type < WD90C30) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if ((svga->bpp >= 8) && !svga->lowres) { svga->render = svga_render_8bpp_highres; - svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; + if (paradise->type != WD90C11) + svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; } } + if (paradise->type == WD90C11) switch (svga->crtc[0x2f] & 0x60) { + case 0x60: case 0x40: + svga->vram_display_mask = 0x3ffff; + break; + case 0x20: + svga->vram_display_mask = 0x7ffff; + break; + case 0x00: + svga->vram_display_mask = 0xfffff; + break; + } } else { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if ((svga->bpp >= 8) && !svga->lowres) { @@ -352,6 +544,52 @@ paradise_recalctimings(svga_t *svga) a windowed DOS box in Win3.x*/ } } + + /* + Yes, this is basically hack but I'm going to look at a proper rewrite in + 86Box 6.0. + */ + if ((paradise->type == WD90C11) && (svga->hdisp == 1024) && + (svga->render == svga_render_4bpp_highres) && paradise_mode_is_word(svga)) + svga->render = paradise_render_4bpp_word_highres; +} + +uint32_t +paradise_decode_addr(paradise_t *paradise, uint32_t addr, int write) +{ + svga_t *svga = ¶dise->svga; + int memory_map_mode = (svga->gdcreg[6] >> 2) & 3; + + addr &= 0x1ffff; + + switch (memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return 0xffffffff; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return 0xffffffff; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return 0xffffffff; + break; + } + + if (memory_map_mode <= 1) { + if (write) + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + else + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + } + + return addr; } static void @@ -362,7 +600,9 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { @@ -395,7 +635,9 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { @@ -428,7 +670,9 @@ paradise_read(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return 0xff; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { @@ -461,7 +705,9 @@ paradise_readw(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; + addr = paradise_decode_addr(paradise, addr, 1); + if (addr == 0xffffffff) + return 0xffff; /*Could be done in a better way but it works.*/ if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c index 2b3eb730a..b4a2d24db 100644 --- a/src/video/vid_pcjr.c +++ b/src/video/vid_pcjr.c @@ -35,6 +35,8 @@ #include <86box/video.h> #include <86box/vid_cga.h> #include <86box/vid_cga_comp.h> +#include <86box/plat_unused.h> +#include "cpu.h" #include <86box/m_pcjr.h> @@ -194,6 +196,16 @@ vid_in(uint16_t addr, void *priv) return ret; } +void +pcjr_waitstates(UNUSED(void *priv)) +{ + int ws_array[16] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 }; + int ws; + + ws = ws_array[cycles & 0xf]; + cycles -= ws; +} + static void vid_write(uint32_t addr, uint8_t val, void *priv) { @@ -202,6 +214,8 @@ vid_write(uint32_t addr, uint8_t val, void *priv) if (pcjr->memctrl == -1) return; + pcjr_waitstates(NULL); + pcjr->b8000[addr & 0x3fff] = val; } @@ -213,6 +227,8 @@ vid_read(uint32_t addr, void *priv) if (pcjr->memctrl == -1) return 0xff; + pcjr_waitstates(NULL); + return (pcjr->b8000[addr & 0x3fff]); } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 8ed71645e..512d5e11e 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1101,8 +1101,8 @@ 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; + disptime_xga = xga->h_total; + _dispontime_xga = xga->h_disp_time; } } @@ -1262,11 +1262,6 @@ svga_do_render(svga_t *svga) if (!svga->override) { svga->render_line_offset = svga->start_retrace_latch - svga->crtc[0x4]; svga->render(svga); - - svga->x_add = svga->left_overscan; - svga_render_overscan_left(svga); - svga_render_overscan_right(svga); - svga->x_add = svga->left_overscan - svga->scrollcache; } if (svga->overlay_on) { @@ -1293,6 +1288,13 @@ svga_do_render(svga_t *svga) if (svga->hwcursor_on && svga->interlace) svga->hwcursor_on--; } + + if (!svga->override) { + svga->x_add = svga->left_overscan; + svga_render_overscan_left(svga); + svga_render_overscan_right(svga); + svga->x_add = svga->left_overscan - svga->scrollcache; + } } void diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 0c3252414..b3a5c0192 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -58,7 +58,7 @@ svga_render_null(svga_t *svga) void svga_render_blank(svga_t *svga) { - if ((svga->displine + svga->y_add) < 0) + if ((svga->displine + svga->y_add) < 0 || (svga->displine + svga->y_add) >= 2048) return; if (svga->firstline_draw == 2000) diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 2e42e5c2c..2834213c7 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -53,39 +53,42 @@ video_cards[] = { { .device = &device_none, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &device_internal, .flags = VIDEO_FLAG_TYPE_NONE }, /* ISA */ + { .device = &ati18800_wonder_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ati18800_vga88_device, .flags = VIDEO_FLAG_TYPE_NONE }, +#ifdef USE_XL24 + { .device = &ati28800_wonderxl24_device, .flags = VIDEO_FLAG_TYPE_NONE }, +#endif /* USE_XL24 */ + { .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 }, { .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 = &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 - { .device = &ati28800_wonderxl24_device, .flags = VIDEO_FLAG_TYPE_NONE }, -#endif /* USE_XL24 */ { .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 = &quadcolor_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 = &colorplus_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 = &cga_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &ega_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &mda_device, .flags = VIDEO_FLAG_TYPE_MDA }, + { .device = &pgc_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &vga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &im1024_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &iskra_ega_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &jega_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 = &nec_sv9000_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 }, @@ -94,9 +97,8 @@ video_cards[] = { { .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 = &quadcolor_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 = &sigma_device, .flags = VIDEO_FLAG_TYPE_NONE }, @@ -104,13 +106,11 @@ video_cards[] = { { .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 = &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 */ diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 4bcf8a479..d80a39a15 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +122,8 @@ typedef struct banshee_t { uint32_t vidProcCfg; uint32_t vidScreenSize; uint32_t vidSerialParallelPort; + uint32_t vidChromaKeyMin; + uint32_t vidChromaKeyMax; uint32_t agpReqSize; uint32_t agpHostAddressHigh; @@ -153,6 +156,8 @@ typedef struct banshee_t { uint8_t pci_slot; uint8_t irq_state; + bool chroma_key_enabled; + void *i2c, *i2c_ddc, *ddc; } banshee_t; @@ -186,6 +191,8 @@ enum { Video_hwCurC0 = 0x68, Video_hwCurC1 = 0x6c, Video_vidSerialParallelPort = 0x78, + Video_vidChromaKeyMin = 0x8c, + Video_vidChromaKeyMax = 0x90, Video_vidScreenSize = 0x98, Video_vidOverlayStartCoords = 0x9c, Video_vidOverlayEndScreenCoords = 0xa0, @@ -946,6 +953,14 @@ banshee_ext_outl(uint16_t addr, uint32_t val, void *priv) i2c_gpio_set(banshee->i2c, !!(val & VIDSERIAL_I2C_SCK_W), !!(val & VIDSERIAL_I2C_SDA_W)); break; + case Video_vidChromaKeyMin: + banshee->vidChromaKeyMin = val; + break; + + case Video_vidChromaKeyMax: + banshee->vidChromaKeyMax = val; + break; + case Video_vidScreenSize: banshee->vidScreenSize = val; voodoo->h_disp = (val & 0xfff) + 1; @@ -1253,6 +1268,12 @@ banshee_ext_inl(uint16_t addr, void *priv) #endif break; + case Video_vidChromaKeyMin: + ret = banshee->vidChromaKeyMin; + break; + case Video_vidChromaKeyMax: + ret = banshee->vidChromaKeyMax; + break; case Video_vidScreenSize: ret = banshee->vidScreenSize; break; @@ -2634,12 +2655,97 @@ voodoo_generate_vb_filters(voodoo_t *voodoo, int fcr, int fcg) } } +/* 1 = render overlay, 0 = render desktop */ +static bool +banshee_chroma_key(banshee_t* banshee, uint32_t x, uint32_t y) +{ + uint32_t src_addr_desktop = banshee->desktop_addr + y * (banshee->vidDesktopOverlayStride & 0x3fff); + bool res = true; + uint8_t chromaKeyMaxIndex = banshee->vidChromaKeyMax & 0xff; + uint8_t chromaKeyMinIndex = banshee->vidChromaKeyMin & 0xff; + uint32_t desktop_pixel = 0; + uint8_t desktop_r = 0; + uint8_t desktop_g = 0; + uint8_t desktop_b = 0; + uint32_t prev_desktop_y = banshee->desktop_y - 1; + + if (!banshee->chroma_key_enabled) + return true; + + if (y > 2048) + return true; + + if (!(banshee->vidProcCfg & (1 << 5))) { + return true; + } + + switch (VIDPROCCFG_DESKTOP_PIX_FORMAT) { + case PIX_FORMAT_8: + { + desktop_pixel = banshee->svga.vram[src_addr_desktop + x]; + res = (desktop_pixel & 0xFF) >= chromaKeyMinIndex && (desktop_pixel & 0xFF) <= chromaKeyMaxIndex; + break; + } + case PIX_FORMAT_RGB565: + { + if (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) { + uint32_t addr = 0; + if (prev_desktop_y & 0x80000000) + return false; + if (banshee->vidProcCfg & VIDPROCCFG_HALF_MODE) + addr = banshee->desktop_addr + ((prev_desktop_y >> 1) & 31) * 128 + ((prev_desktop_y >> 6) * banshee->desktop_stride_tiled); + else + addr = banshee->desktop_addr + (prev_desktop_y & 31) * 128 + ((prev_desktop_y >> 5) * banshee->desktop_stride_tiled); + + addr += 128 * 32 * (x >> 6); + addr += (x & 63) * 2; + desktop_pixel = *(uint16_t*)&banshee->svga.vram[addr & banshee->svga.vram_mask]; + } else { + desktop_pixel = *(uint16_t*)&banshee->svga.vram[(src_addr_desktop + x * 2) & banshee->svga.vram_mask]; + } + + desktop_r = (desktop_pixel & 0x1f); + desktop_g = (desktop_pixel & 0x7e0) >> 5; + desktop_b = (desktop_pixel & 0xf800) >> 11; + + res = (desktop_r >= ((banshee->vidChromaKeyMin >> 11) & 0x1F) && desktop_r <= ((banshee->vidChromaKeyMax >> 11) & 0x1F)) && + (desktop_g >= ((banshee->vidChromaKeyMin >> 5) & 0x3F) && desktop_g <= ((banshee->vidChromaKeyMax >> 5) & 0x3F)) && + (desktop_b >= ((banshee->vidChromaKeyMin) & 0x1F) && desktop_b <= ((banshee->vidChromaKeyMax) & 0x1F)); + break; + } + case PIX_FORMAT_RGB24: + { + desktop_r = banshee->svga.vram[(src_addr_desktop + x * 3) & banshee->svga.vram_mask]; + desktop_g = banshee->svga.vram[(src_addr_desktop + x * 3 + 1) & banshee->svga.vram_mask]; + desktop_b = banshee->svga.vram[(src_addr_desktop + x * 3 + 2) & banshee->svga.vram_mask]; + res = (desktop_r >= ((banshee->vidChromaKeyMin >> 16) & 0xFF) && desktop_r <= ((banshee->vidChromaKeyMax >> 16) & 0xFF)) && + (desktop_g >= ((banshee->vidChromaKeyMin >> 8) & 0xFF) && desktop_g <= ((banshee->vidChromaKeyMax >> 8) & 0xFF)) && + (desktop_b >= ((banshee->vidChromaKeyMin) & 0xFF) && desktop_b <= ((banshee->vidChromaKeyMax) & 0xFF)); + break; + } + case PIX_FORMAT_RGB32: + { + desktop_r = banshee->svga.vram[(src_addr_desktop + x * 4) & banshee->svga.vram_mask]; + desktop_g = banshee->svga.vram[(src_addr_desktop + x * 4 + 1) & banshee->svga.vram_mask]; + desktop_b = banshee->svga.vram[(src_addr_desktop + x * 4 + 2) & banshee->svga.vram_mask]; + res = (desktop_r >= ((banshee->vidChromaKeyMin >> 16) & 0xFF) && desktop_r <= ((banshee->vidChromaKeyMax >> 16) & 0xFF)) && + (desktop_g >= ((banshee->vidChromaKeyMin >> 8) & 0xFF) && desktop_g <= ((banshee->vidChromaKeyMax >> 8) & 0xFF)) && + (desktop_b >= ((banshee->vidChromaKeyMin) & 0xFF) && desktop_b <= ((banshee->vidChromaKeyMax) & 0xFF)); + break; + } + } + + res ^= !!(banshee->vidProcCfg & (1 << 6)); + return res; +} + static void banshee_overlay_draw(svga_t *svga, int displine) { banshee_t *banshee = (banshee_t *) svga->priv; voodoo_t *voodoo = banshee->voodoo; uint32_t *p; + bool chroma_test_passed = true; int x; int y = voodoo->overlay.src_y >> 20; uint32_t src_addr = svga->overlay_latch.addr + ((banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) ? ((y & 31) * 128 + (y >> 5) * svga->overlay_latch.pitch) : y * svga->overlay_latch.pitch); @@ -2654,6 +2760,8 @@ banshee_overlay_draw(svga_t *svga, int displine) voodoo->overlay.src_y += (1 << 20); return; } + + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x, displine - svga->y_add); if ((voodoo->overlay.src_y >> 20) < 2048) voodoo->dirty_line[voodoo->overlay.src_y >> 20] = 0; @@ -2671,7 +2779,8 @@ banshee_overlay_draw(svga_t *svga, int displine) if (skip_filtering) { /*No scaling or filtering required, just write straight to output buffer*/ - OVERLAY_SAMPLE(p); + if (chroma_test_passed) + OVERLAY_SAMPLE(p); } else { OVERLAY_SAMPLE(banshee->overlay_buffer[0]); @@ -2688,25 +2797,31 @@ banshee_overlay_draw(svga_t *svga, int displine) ((0x10000 - x_coeff) * y_coeff) >> 16, (x_coeff * y_coeff) >> 16 }; - uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; - uint32_t samp1 = banshee->overlay_buffer[0][(src_x >> 20) + 1]; - uint32_t samp2 = banshee->overlay_buffer[1][src_x >> 20]; - uint32_t samp3 = banshee->overlay_buffer[1][(src_x >> 20) + 1]; - int r = (((samp0 >> 16) & 0xff) * coeffs[0] + ((samp1 >> 16) & 0xff) * coeffs[1] + ((samp2 >> 16) & 0xff) * coeffs[2] + ((samp3 >> 16) & 0xff) * coeffs[3]) >> 16; - int g = (((samp0 >> 8) & 0xff) * coeffs[0] + ((samp1 >> 8) & 0xff) * coeffs[1] + ((samp2 >> 8) & 0xff) * coeffs[2] + ((samp3 >> 8) & 0xff) * coeffs[3]) >> 16; - int b = ((samp0 & 0xff) * coeffs[0] + (samp1 & 0xff) * coeffs[1] + (samp2 & 0xff) * coeffs[2] + (samp3 & 0xff) * coeffs[3]) >> 16; - p[x] = (r << 16) | (g << 8) | b; + uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; + uint32_t samp1 = banshee->overlay_buffer[0][(src_x >> 20) + 1]; + uint32_t samp2 = banshee->overlay_buffer[1][src_x >> 20]; + uint32_t samp3 = banshee->overlay_buffer[1][(src_x >> 20) + 1]; + int r = (((samp0 >> 16) & 0xff) * coeffs[0] + ((samp1 >> 16) & 0xff) * coeffs[1] + ((samp2 >> 16) & 0xff) * coeffs[2] + ((samp3 >> 16) & 0xff) * coeffs[3]) >> 16; + int g = (((samp0 >> 8) & 0xff) * coeffs[0] + ((samp1 >> 8) & 0xff) * coeffs[1] + ((samp2 >> 8) & 0xff) * coeffs[2] + ((samp3 >> 8) & 0xff) * coeffs[3]) >> 16; + int b = ((samp0 & 0xff) * coeffs[0] + (samp1 & 0xff) * coeffs[1] + (samp2 & 0xff) * coeffs[2] + (samp3 & 0xff) * coeffs[3]) >> 16; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + + if (chroma_test_passed) + p[x] = (r << 16) | (g << 8) | b; src_x += voodoo->overlay.vidOverlayDudx; } } else { for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { - uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; - uint32_t samp1 = banshee->overlay_buffer[1][src_x >> 20]; - int r = (((samp0 >> 16) & 0xff) * (0x10000 - y_coeff) + ((samp1 >> 16) & 0xff) * y_coeff) >> 16; - int g = (((samp0 >> 8) & 0xff) * (0x10000 - y_coeff) + ((samp1 >> 8) & 0xff) * y_coeff) >> 16; - int b = ((samp0 & 0xff) * (0x10000 - y_coeff) + (samp1 & 0xff) * y_coeff) >> 16; - p[x] = (r << 16) | (g << 8) | b; + uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20]; + uint32_t samp1 = banshee->overlay_buffer[1][src_x >> 20]; + int r = (((samp0 >> 16) & 0xff) * (0x10000 - y_coeff) + ((samp1 >> 16) & 0xff) * y_coeff) >> 16; + int g = (((samp0 >> 8) & 0xff) * (0x10000 - y_coeff) + ((samp1 >> 8) & 0xff) * y_coeff) >> 16; + int b = ((samp0 & 0xff) * (0x10000 - y_coeff) + (samp1 & 0xff) * y_coeff) >> 16; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + + if (chroma_test_passed) + p[x] = (r << 16) | (g << 8) | b; } } break; @@ -2761,21 +2876,30 @@ banshee_overlay_draw(svga_t *svga, int displine) fil3[x * 3 + 2] = vb_filter_v1_rb[fil[x * 3 + 2]][fil[(x - 1) * 3 + 2]]; } for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { - fil[x * 3] = vb_filter_v1_rb[fil[x * 3]][fil3[(x + 1) * 3]]; - fil[x * 3 + 1] = vb_filter_v1_g[fil[x * 3 + 1]][fil3[(x + 1) * 3 + 1]]; - fil[x * 3 + 2] = vb_filter_v1_rb[fil[x * 3 + 2]][fil3[(x + 1) * 3 + 2]]; - p[x] = (fil[x * 3 + 2] << 16) | (fil[x * 3 + 1] << 8) | fil[x * 3]; + fil[x * 3] = vb_filter_v1_rb[fil[x * 3]][fil3[(x + 1) * 3]]; + fil[x * 3 + 1] = vb_filter_v1_g[fil[x * 3 + 1]][fil3[(x + 1) * 3 + 1]]; + fil[x * 3 + 2] = vb_filter_v1_rb[fil[x * 3 + 2]][fil3[(x + 1) * 3 + 2]]; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + + if (chroma_test_passed) + p[x] = (fil[x * 3 + 2] << 16) | (fil[x * 3 + 1] << 8) | fil[x * 3]; } } else /* filter disabled by emulator option */ { if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) { for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { - p[x] = banshee->overlay_buffer[0][src_x >> 20]; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = banshee->overlay_buffer[0][src_x >> 20]; + src_x += voodoo->overlay.vidOverlayDudx; } } else { - for (x = 0; x < svga->overlay_latch.cur_xsize; x++) - p[x] = banshee->overlay_buffer[0][x]; + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = banshee->overlay_buffer[0][x]; + } } } break; @@ -2830,25 +2954,35 @@ banshee_overlay_draw(svga_t *svga, int displine) if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* 2x2 on a scaled low res */ { for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { - p[x] = (fil[(src_x >> 20) * 3 + 2] << 16) | (fil[(src_x >> 20) * 3 + 1] << 8) | fil[(src_x >> 20) * 3]; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = (fil[(src_x >> 20) * 3 + 2] << 16) | (fil[(src_x >> 20) * 3 + 1] << 8) | fil[(src_x >> 20) * 3]; + src_x += voodoo->overlay.vidOverlayDudx; } } else { for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { - p[x] = (fil[x * 3 + 2] << 16) | (fil[x * 3 + 1] << 8) | fil[x * 3]; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = (fil[x * 3 + 2] << 16) | (fil[x * 3 + 1] << 8) | fil[x * 3]; } } } else /* filter disabled by emulator option */ { if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) { for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { - p[x] = banshee->overlay_buffer[0][src_x >> 20]; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = banshee->overlay_buffer[0][src_x >> 20]; src_x += voodoo->overlay.vidOverlayDudx; } } else { - for (x = 0; x < svga->overlay_latch.cur_xsize; x++) - p[x] = banshee->overlay_buffer[0][x]; + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = banshee->overlay_buffer[0][x]; + } } } break; @@ -2857,13 +2991,18 @@ banshee_overlay_draw(svga_t *svga, int displine) default: if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) { for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { - p[x] = banshee->overlay_buffer[0][src_x >> 20]; + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = banshee->overlay_buffer[0][src_x >> 20]; src_x += voodoo->overlay.vidOverlayDudx; } } else { - for (x = 0; x < svga->overlay_latch.cur_xsize; x++) - p[x] = banshee->overlay_buffer[0][x]; + for (x = 0; x < svga->overlay_latch.cur_xsize; x++) { + chroma_test_passed = banshee_chroma_key(banshee, svga->overlay_latch.x + x, displine - svga->y_add); + if (chroma_test_passed) + p[x] = banshee->overlay_buffer[0][x]; + } } break; } @@ -3262,6 +3401,8 @@ banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int banshee->agp = agp; banshee->has_bios = !!fn; + banshee->chroma_key_enabled = device_get_config_int("chromakey"); + if (banshee->has_bios) { rom_init(&banshee->bios_rom, fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_disable(&banshee->bios_rom.mapping); @@ -3692,6 +3833,17 @@ static const device_config_t banshee_sgram_config[] = { .selection = { { 0 } }, .bios = { { 0 } } }, + { + .name = "chromakey", + .description = "Video chroma-keying", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "dithersub", .description = "Dither subtraction", @@ -3758,6 +3910,17 @@ static const device_config_t banshee_sgram_16mbonly_config[] = { .selection = { { 0 } }, .bios = { { 0 } } }, + { + .name = "chromakey", + .description = "Video chroma-keying", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "dithersub", .description = "Dither subtraction", @@ -3824,6 +3987,17 @@ static const device_config_t banshee_sdram_config[] = { .selection = { { 0 } }, .bios = { { 0 } } }, + { + .name = "chromakey", + .description = "Video chroma-keying", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, { .name = "dithersub", .description = "Dither subtraction", diff --git a/src/video/vid_voodoo_banshee_blitter.c b/src/video/vid_voodoo_banshee_blitter.c index 4dc39f332..cf2824bba 100644 --- a/src/video/vid_voodoo_banshee_blitter.c +++ b/src/video/vid_voodoo_banshee_blitter.c @@ -917,7 +917,19 @@ do_screen_to_screen_stretch_line(voodoo_t *voodoo, uint8_t *src_p, int src_x, in const uint8_t *pattern_mono = (uint8_t *) voodoo->banshee_blt.colorPattern; int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) == (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO); const uint32_t *colorPattern = voodoo->banshee_blt.colorPattern; + int src_colorkey; + switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) { + case SRC_FORMAT_COL_8_BPP: + src_colorkey = COLORKEY_8; + break; + case SRC_FORMAT_COL_16_BPP: + src_colorkey = COLORKEY_16; + break; + default: + src_colorkey = COLORKEY_32; + break; + } #if 0 int error_y = voodoo->banshee_blt.dstSizeY / 2; @@ -925,104 +937,218 @@ do_screen_to_screen_stretch_line(voodoo_t *voodoo, uint8_t *src_p, int src_x, in bansheeblt_log(" srcXY=%i,%i srcsizeXY=%i,%i\n", voodoo->banshee_blt.srcX, voodoo->banshee_blt.srcY, voodoo->banshee_blt.srcSizeX, voodoo->banshee_blt.srcSizeY); bansheeblt_log(" dstXY=%i,%i dstsizeXY=%i,%i\n", voodoo->banshee_blt.dstX, voodoo->banshee_blt.dstY, voodoo->banshee_blt.dstSizeX, voodoo->banshee_blt.dstSizeY);*/ #endif - if (dst_y >= clip->y_min && dst_y < clip->y_max) { -#if 0 - int src_x = voodoo->banshee_blt.srcX; -#endif - int dst_x = voodoo->banshee_blt.dstX; - int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; - uint8_t pattern_mask = pattern_mono[pat_y & 7]; - int error_x = voodoo->banshee_blt.dstSizeX / 2; + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK)) { + if (dst_y >= clip->y_min && dst_y < clip->y_max) { + int dst_x = voodoo->banshee_blt.dstX; + int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; + uint8_t pattern_mask = pattern_mono[pat_y & 7]; + int error_x = voodoo->banshee_blt.dstSizeX / 2; -#if 0 - bansheeblt_log(" Plot dest line %03i : src line %03i\n", dst_y, src_y); -#endif - for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) { - int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; + for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) { + int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; - if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) { - switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) { - case DST_FORMAT_COL_8_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = src_p[src_x]; - uint32_t dest = voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; + if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) { + switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) { + case DST_FORMAT_COL_8_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = src_p[src_x]; + uint32_t dest = voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; - if (dst_addr > voodoo->fb_mask) + if (dst_addr > voodoo->fb_mask) + break; + + voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8); + voodoo->changedvram[dst_addr >> 12] = changeframecount; break; + } + case DST_FORMAT_COL_16_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x * 2, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint16_t *) &src_p[src_x * 2]; + uint32_t dest = *(uint16_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; - voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8); -#if 0 - bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); -#endif - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_16_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x * 2, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint16_t *) &src_p[src_x * 2]; - uint32_t dest = *(uint16_t *) &voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; + if (dst_addr > voodoo->fb_mask) + break; - if (dst_addr > voodoo->fb_mask) + *(uint16_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16); + voodoo->changedvram[dst_addr >> 12] = changeframecount; break; + } + case DST_FORMAT_COL_24_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x * 3, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint32_t *) &src_p[src_x * 3]; + uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; - *(uint16_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16); -#if 0 - bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, *(uint16_t *)&voodoo->vram[dst_addr]); -#endif - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_24_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x * 3, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint32_t *) &src_p[src_x * 3]; - uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; + if (dst_addr > voodoo->fb_mask) + break; - if (dst_addr > voodoo->fb_mask) + *(uint32_t *) &voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (*(uint32_t *) &voodoo->vram[dst_addr] & 0xff000000); + voodoo->changedvram[dst_addr >> 12] = changeframecount; break; + } + case DST_FORMAT_COL_32_BPP: + { + uint32_t dst_addr = get_addr(voodoo, dst_x * 4, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; + uint32_t src = *(uint32_t *) &src_p[src_x * 4]; + uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; + uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; - *(uint32_t *) &voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (*(uint32_t *) &voodoo->vram[dst_addr] & 0xff000000); -#if 0 - bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); -#endif - voodoo->changedvram[dst_addr >> 12] = changeframecount; - break; - } - case DST_FORMAT_COL_32_BPP: - { - uint32_t dst_addr = get_addr(voodoo, dst_x * 4, dst_y, 0, 0); //(voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask; - uint32_t src = *(uint32_t *) &src_p[src_x * 4]; - uint32_t dest = *(uint32_t *) &voodoo->vram[dst_addr]; - uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ? ((pattern_mask & (1 << (7 - (pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) : colorPattern[(pat_x & 7) + (pat_y & 7) * 8]; + if (dst_addr > voodoo->fb_mask) + break; - if (dst_addr > voodoo->fb_mask) + *(uint32_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32); + voodoo->changedvram[dst_addr >> 12] = changeframecount; break; + } - *(uint32_t *) &voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32); -#if 0 - bansheeblt_log("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]); -#endif - voodoo->changedvram[dst_addr >> 12] = changeframecount; + default: break; - } - - default: - break; + } } - } - error_x -= voodoo->banshee_blt.srcSizeX; - while (error_x < 0) { - error_x += voodoo->banshee_blt.dstSizeX; - src_x++; + error_x -= voodoo->banshee_blt.srcSizeX; + while (error_x < 0) { + error_x += voodoo->banshee_blt.dstSizeX; + src_x++; + } + dst_x++; + pat_x++; + } + } + } else { + /* Color conversion required. */ + if (dst_y >= clip->y_min && dst_y < clip->y_max) { + int dst_x = voodoo->banshee_blt.dstX; + int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX; + uint8_t pattern_mask = pattern_mono[pat_y & 7]; + int error_x = voodoo->banshee_blt.dstSizeX / 2; + + for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++) { + int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7 - (pat_x & 7)))) : 1; + int src_x_real = (src_x * voodoo->banshee_blt.src_bpp) >> 3; + + if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans) { + uint32_t src_data = 0; + uint32_t src_data_yuv = 0; /* Used in YUYV-to-RGB convesions. */ + int transparent = 0; + + switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) { + case SRC_FORMAT_COL_1_BPP: + { + uint8_t src_byte = src_p[src_x_real]; + src_data = (src_byte & (0x80 >> (src_x & 7))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack; + if (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) + transparent = !(src_byte & (0x80 >> (src_x & 7))); +#if 0 + bansheeblt_log(" 1bpp src_byte=%02x src_x=%i src_data=%x transparent=%i\n", src_byte, src_x, src_data, transparent); +#endif + break; + } + case SRC_FORMAT_COL_8_BPP: + { + src_data = src_p[src_x_real]; + break; + } + case SRC_FORMAT_COL_16_BPP: + { + uint16_t src_16 = *(uint16_t *) &src_p[src_x_real]; + int r = (src_16 >> 11); + int g = (src_16 >> 5) & 0x3f; + int b = src_16 & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 2) | (g >> 4); + b = (b << 3) | (b >> 2); + src_data = (r << 16) | (g << 8) | b; + break; + } + case SRC_FORMAT_COL_24_BPP: + { + src_data = *(uint32_t *) &src_p[src_x_real]; + break; + } + case SRC_FORMAT_COL_32_BPP: + { + src_data = *(uint32_t *) &src_p[src_x_real]; + break; + } + case SRC_FORMAT_COL_YUYV: + { + src_data_yuv = *(uint32_t *) &src_p[src_x_real]; + break; + } + case SRC_FORMAT_COL_UYVY: + { + src_data_yuv = *(uint32_t *) &src_p[src_x_real]; + src_data_yuv = ((src_data_yuv & 0xFF00) >> 8) | ((src_data_yuv & 0xFF) << 8) | + ((src_data_yuv & 0xFF000000) >> 8) | ((src_data_yuv & 0xFF0000) << 8); + break; + } + + default: + fatal("banshee_do_screen_to_screen_stretch_blt: unknown srcFormat %08x\n", voodoo->banshee_blt.srcFormat); + } + + if ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_16_BPP && (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) != SRC_FORMAT_COL_1_BPP) { + int r = src_data >> 16; + int g = (src_data >> 8) & 0xff; + int b = src_data & 0xff; + + src_data = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + } + + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_YUYV + || (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_UYVY) { + if (((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_24_BPP) || + ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_32_BPP)) { + uint32_t rgbcol[2] = { 0, 0 }; + DECODE_YUYV422(rgbcol, (uint8_t *) &src_data_yuv); + + bansheeblt_log("YUV -> 24 bpp or 32 bpp\n"); + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, 0xFF, rgbcol[0], src_colorkey); + } + dst_x++; + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, 0xFF, rgbcol[1], src_colorkey); + } + } else if ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_16_BPP) { + uint32_t rgbcol = 0; + DECODE_YUYV422_16BPP((uint16_t *) &rgbcol, (uint8_t *) &src_data_yuv); + + bansheeblt_log("YUV -> 16 bpp\n"); + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, 0xFF, rgbcol & 0xffff, src_colorkey); + } + dst_x++; + + if (!transparent) { + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, 0xFF, rgbcol >> 16, src_colorkey); + } + } else + fatal("banshee_do_screen_to_screen_stretch_blt: unknown dstFormat %08x\n", voodoo->banshee_blt.dstFormat); + } else { + if (!transparent) + PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, 0xFF, src_data, src_colorkey); + } + } + + error_x -= voodoo->banshee_blt.srcSizeX; + while (error_x < 0) { + error_x += voodoo->banshee_blt.dstSizeX; + src_x++; + } + dst_x++; + pat_x++; } - dst_x++; - pat_x++; } } diff --git a/src/video/vid_voodoo_reg.c b/src/video/vid_voodoo_reg.c index ce3ee6064..82dfde354 100644 --- a/src/video/vid_voodoo_reg.c +++ b/src/video/vid_voodoo_reg.c @@ -965,10 +965,12 @@ voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) if (chip & CHIP_TREX0) { voodoo->params.textureMode[0] = val; voodoo->params.tformat[0] = (val >> 8) & 0xf; + voodoo_recalc_tex(voodoo, 0); } if (chip & CHIP_TREX1) { voodoo->params.textureMode[1] = val; voodoo->params.tformat[1] = (val >> 8) & 0xf; + voodoo_recalc_tex(voodoo, 1); } break; case SST_tLOD: diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 8f4dc0d0e..91a2ce500 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -35,6 +35,7 @@ #include <86box/vid_svga_render.h> #include <86box/vid_xga_device.h> #include "cpu.h" +#include <86box/plat.h> #include <86box/plat_unused.h> #define XGA_BIOS_PATH "roms/video/xga/XGA_37F9576_Ver200.BIN" @@ -161,31 +162,19 @@ xga_updatemapping(svga_t *svga) switch (xga->op_mode & 7) { case 0: xga_log("XGA: VGA mode address decode disabled.\n"); + mem_mapping_disable(&xga->linear_mapping); break; case 1: xga_log("XGA: VGA mode address decode enabled.\n"); - if (xga->base_addr_1mb) { - mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); - mem_mapping_enable(&xga->linear_mapping); - } else if (xga->linear_base) { - mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); - mem_mapping_enable(&xga->linear_mapping); - } else - mem_mapping_disable(&xga->linear_mapping); + mem_mapping_disable(&xga->linear_mapping); break; case 2: xga_log("XGA: 132-Column mode address decode disabled.\n"); + mem_mapping_disable(&xga->linear_mapping); break; case 3: xga_log("XGA: 132-Column mode address decode enabled.\n"); - if (xga->base_addr_1mb) { - mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); - mem_mapping_enable(&xga->linear_mapping); - } else if (xga->linear_base) { - mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); - mem_mapping_enable(&xga->linear_mapping); - } else - mem_mapping_disable(&xga->linear_mapping); + mem_mapping_disable(&xga->linear_mapping); break; default: xga_log("XGA: Extended Graphics mode, ap=%d.\n", xga->aperture_cntl); @@ -225,12 +214,14 @@ xga_updatemapping(svga_t *svga) } break; case 1: + mem_mapping_disable(&xga->linear_mapping); xga_log("XGA: 64KB aperture at A0000.\n"); mem_mapping_set_handler(&svga->mapping, xga_read, xga_readw, xga_readl, xga_write, xga_writew, xga_writel); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); xga->banked_mask = 0xffff; break; case 2: + mem_mapping_disable(&xga->linear_mapping); xga_log("XGA: 64KB aperture at B0000.\n"); mem_mapping_set_handler(&svga->mapping, xga_read, xga_readw, xga_readl, xga_write, xga_writew, xga_writel); mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x10000); @@ -276,6 +267,7 @@ xga_recalctimings(svga_t *svga) xga->v_blankstart = xga->vblankstart + 1; xga->h_disp = (xga->hdisp + 1) << 3; + xga->h_disp_time = xga->h_disp >> 3; xga->rowoffset = xga->pix_map_width; @@ -292,7 +284,6 @@ xga_recalctimings(svga_t *svga) 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); switch ((xga->clk_sel_1 >> 2) & 3) { case 0: @@ -329,6 +320,8 @@ xga_recalctimings(svga_t *svga) svga->render_xga = xga_render_blank; break; } + + xga_log("XGA: H_TOTAL=%d, rowoffset=%x, rowcount=%x, memaddr_latch=%06x, bpp type=%d.\n", xga->h_total, xga->rowoffset, xga->rowcount, xga->memaddr_latch, xga->disp_cntl_2 & 7); } } @@ -522,19 +515,40 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) xga->dac_pos++; break; case 1: - xga->dac_g = val; + if (xga->pal_seq & 0x04) + xga->pal_b = val; + else + xga->dac_g = val; + xga->dac_pos++; break; case 2: - xga->pal_b = val; - index = xga->dac_addr & 0xff; - xga->xgapal[index].r = xga->dac_r; - xga->xgapal[index].g = xga->dac_g; - xga->xgapal[index].b = xga->pal_b; - xga->pallook[index] = makecol32(xga->xgapal[index].r, xga->xgapal[index].g, xga->xgapal[index].b); - xga_log("XGA Pallook=%06x, idx=%d.\n", xga->pallook[index], index); - xga->dac_pos = 0; - xga->dac_addr = (xga->dac_addr + 1) & 0xff; + if (xga->pal_seq & 0x04) { + xga->dac_g = val; + xga->dac_pos++; + } else { + xga->pal_b = val; + index = xga->dac_addr & 0xff; + xga->xgapal[index].r = xga->dac_r; + xga->xgapal[index].g = xga->dac_g; + xga->xgapal[index].b = xga->pal_b; + xga->pallook[index] = makecol32(xga->xgapal[index].r, xga->xgapal[index].g, xga->xgapal[index].b); + xga_log("XGA Pallook=%06x, idx=%d.\n", xga->pallook[index], index); + xga->dac_pos = 0; + xga->dac_addr = (xga->dac_addr + 1) & 0xff; + } + break; + case 3: + if (xga->pal_seq & 0x04) { + index = xga->dac_addr & 0xff; + xga->xgapal[index].r = xga->dac_r; + xga->xgapal[index].b = xga->pal_b; + xga->xgapal[index].g = xga->dac_g; + xga->pallook[index] = makecol32(xga->xgapal[index].r, xga->xgapal[index].g, xga->xgapal[index].b); + xga_log("XGA Pallook=%06x, idx=%d.\n", xga->pallook[index], index); + xga->dac_pos = 0; + xga->dac_addr = (xga->dac_addr + 1) & 0xff; + } break; default: @@ -580,13 +594,21 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv) xga->aperture_cntl = val & 3; xga_updatemapping(svga); break; + case 4: + xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); + xga->int_ena = val; + break; + case 5: + xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); + xga->int_stat = val; + break; case 8: xga->ap_idx = val; xga_log("Aperture CNTL = %d, val = %02x, up to bit6 = %02x\n", xga->aperture_cntl, val, val & 0x3f); - if ((xga->op_mode & 7) < 4) { + if ((xga->op_mode & 7) < 4) xga->write_bank = xga->read_bank = 0; - } else { + else { if (xga->base_addr_1mb) { if (xga->aperture_cntl) { xga->write_bank = (xga->ap_idx & 0x3f) << 16; @@ -638,6 +660,12 @@ xga_ext_inb(uint16_t addr, void *priv) case 1: ret = xga->aperture_cntl; break; + case 4: + ret = xga->int_ena; + break; + case 5: + ret = xga->int_stat; + break; case 8: ret = xga->ap_idx; break; @@ -801,12 +829,26 @@ xga_ext_inb(uint16_t addr, void *priv) break; case 1: xga->dac_pos++; - ret = xga->xgapal[index].g; + if (xga->pal_seq & 0x04) + ret = xga->xgapal[index].b; + else + ret = xga->xgapal[index].g; break; case 2: - xga->dac_pos = 0; - xga->dac_addr = (xga->dac_addr + 1) & 0xff; - ret = xga->xgapal[index].b; + if (xga->pal_seq & 0x04) { + xga->dac_pos++; + ret = xga->xgapal[index].g; + } else { + xga->dac_pos = 0; + xga->dac_addr = (xga->dac_addr + 1) & 0xff; + ret = xga->xgapal[index].b; + } + break; + case 3: + if (xga->pal_seq & 0x04) { + xga->dac_pos = 0; + xga->dac_addr = (xga->dac_addr + 1) & 0xff; + } break; default: @@ -856,20 +898,6 @@ xga_ext_inb(uint16_t addr, void *priv) return ret; } -#define READ(addr, dat) \ - dat = xga->vram[(addr) & (xga->vram_mask)]; - -#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) \ - dat = *(uint16_t *) &xga->vram[(addr) & (xga->vram_mask)]; - -#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) \ { \ switch ((mix) ? (xga->accel.frgd_mix & 0x1f) : (xga->accel.bkgd_mix & 0x1f)) { \ @@ -943,218 +971,255 @@ xga_ext_inb(uint16_t addr, void *priv) } static uint32_t -xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, uint32_t base, int width) +xga_transform_addr(uint32_t addr, uint8_t mode) { - const xga_t *xga = (xga_t *) svga->xga; - uint32_t addr = base; - int bits; - uint8_t byte; - uint8_t px; - int skip = 0; + uint32_t ret = addr; - if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) - skip = 1; + if ((mode & 0x0f) == 0x0c) + ret ^= 1; - addr += (y * (width >> 3)); - addr += (x >> 3); - if (!skip) { - READ(addr, byte); - } else - byte = mem_readb_phys(addr); + return ret; +} - bits = 7 - (x & 7); +static uint16_t +xga_transform_val(uint16_t val, uint8_t mode, int bits) +{ + uint16_t ret = 0x0000; - xga_log("0. AccessMode=%02x, SRCMAP=%02x, DSTMAP=%02x, PAT=%02x.\n", xga->access_mode & 0x0f, (xga->accel.px_map_format[xga->accel.src_map] & 0x0f), (xga->accel.px_map_format[xga->accel.dst_map] & 0x0f), (xga->accel.px_map_format[xga->accel.pat_src] & 0x08)); - if (!(xga->accel.px_map_format[xga->accel.src_map] & 0x08) && !(xga->accel.px_map_format[xga->accel.dst_map] & 0x08)) { - if (((xga->accel.px_map_format[xga->accel.src_map] & 0x07) >= 0x02) && ((xga->accel.px_map_format[xga->accel.dst_map] & 0x07) >= 0x02) && (xga->accel.pat_src <= 2)) - bits ^= 7; + switch (mode & 0x0f) { + default: + ret = val; + break; + case 0x08: /* 1 bpp */ + for (int i = 0; i < bits; i++) + ret |= ((val >> i) & 0x01) << (i ^ 7); + break; + case 0x09: /* 2 bpp */ + for (int i = 0; i < bits; i += 2) + ret |= ((val >> i) & 0x03) << (i ^ 6); + break; + case 0x0a: /* 4 bpp */ + for (int i = 0; i < bits; i += 4) + ret |= ((val >> i) & 0x0f) << (i ^ 4); + break; + case 0x0c: /* 16 bpp */ + if (bits == 16) for (int i = 0; i < (bits >> 3); i++) + ret |= ((val >> (i << 3)) & 0xff) << ((i << 3) ^ 8); + else + ret = val; + break; } - px = (byte >> bits) & 1; - return px; + return ret & ((1 << bits) - 1); } -static uint32_t -xga_accel_read_area_map_pixel(svga_t *svga, int x, int y, uint32_t base, int width) +static uint8_t +xga_map_readb(svga_t *svga, uint32_t addr, int map) { - const xga_t *xga = (xga_t *) svga->xga; - uint32_t addr = base; - int bits; - uint8_t byte; - uint8_t px; - int skip = 0; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret; - if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) - skip = 1; + if ((addr >= xga->linear_base) && (addr <= (xga->linear_base + 0xfffff))) + ret = xga->vram[addr & xga->vram_mask]; + else + ret = xga_transform_val(mem_readb_phys(xga_transform_addr(addr, xga->accel.px_map_format[map])), + xga->accel.px_map_format[map], 8); + return ret; +} - addr += (y * (width >> 3)); - addr += (x >> 3); - if (!skip) { - READ(addr, byte); +static uint16_t +xga_map_readw(svga_t *svga, uint32_t addr, int map) +{ + xga_t *xga = (xga_t *) svga->xga; + uint16_t ret; + + if ((addr >= xga->linear_base) && (addr <= (xga->linear_base + 0xfffff))) + ret = *(uint16_t *) &xga->vram[addr & xga->vram_mask]; + else + ret = xga_transform_val(mem_readw_phys(addr), xga->accel.px_map_format[map], 16); + + return ret; +} + +static void +xga_map_writeb(svga_t *svga, uint32_t addr, int map, uint8_t val) +{ + xga_t *xga = (xga_t *) svga->xga; + + if ((addr >= xga->linear_base) && (addr <= (xga->linear_base + 0xfffff))) { + xga->vram[addr & xga->vram_mask] = val; + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; } else - byte = mem_readb_phys(addr); + mem_writeb_phys(xga_transform_addr(addr, xga->accel.px_map_format[map]), + xga_transform_val(val, xga->accel.px_map_format[map], 8)); +} - bits = 7 - (x & 7); +static void +xga_map_writew(svga_t *svga, uint32_t addr, int map, uint16_t val) +{ + xga_t *xga = (xga_t *) svga->xga; - px = (byte >> bits) & 1; - return px; + if ((addr >= xga->linear_base) && (addr <= (xga->linear_base + 0xfffff))) { + *(uint16_t *) &xga->vram[addr & xga->vram_mask] = val; + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; + } else + mem_writew_phys(addr, xga_transform_val(val, xga->accel.px_map_format[map], 16)); +} + +static int +xga_calc_pos(int x, int y, int width) +{ + int ret = (y * (width + 1)) + (x % (width + 1)); + + return ret; } static uint32_t -xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int width) +xga_add_to_addr(xga_t *xga, uint32_t addr, int pos, int map) { - xga_t *xga = (xga_t *) svga->xga; - uint32_t addr = base; - int bits; - uint32_t byte; - uint8_t px; - int skip = 0; + int pos_div[8] = { 8, 4, 2, 1, 1, 1, 1, 1 }; + int pos_mul[8] = { 1, 1, 1, 1, 2, 1, 1, 1 }; + int div_val = pos_div[xga->accel.px_map_format[map] & 0x07]; + int mul_val = pos_mul[xga->accel.px_map_format[map] & 0x07]; + uint32_t ret = addr + ((pos / div_val) * mul_val); - if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) - skip = 1; + return ret; +} + +#define READ_MAP(base, pos, map) xga_map_readb(svga, xga_add_to_addr(xga, base, pos, map), map) +#define READ_MAPW(base, pos, map) xga_map_readw(svga, xga_add_to_addr(xga, base, pos, map), map) +#define WRITE_MAP(base, pos, map, val) xga_map_writeb(svga, xga_add_to_addr(xga, base, pos, map), map, val) +#define WRITE_MAPW(base, pos, map, val) xga_map_writew(svga, xga_add_to_addr(xga, base, pos, map), map, val) + +#define DO_READ_MAP(map) READ_MAP(base, pos, map) + +#define PIXEL_MASK(bits) (0x07 / bits) +#define ALL_SET(bits) ((1 << bits) - 1) + +#define MASK(map, bits) ((pos & PIXEL_MASK(bits)) * bits) +#define MASKED_READ(map, bits) (DO_READ_MAP(map) >> MASK(map, bits)) & ALL_SET(bits) + +static uint32_t +xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y) +{ + xga_t *xga = (xga_t *) svga->xga; + int map = 0; + uint32_t ret = 0x000000ff; + + switch ((xga->accel.command >> 12) & 0x0f) { + default: + case 8: + map = 0; + break; + case 1 ... 3: + map = (xga->accel.command >> 12) & 0x0f; + break; + case 9: + map = (xga->accel.command >> 20) & 0x0f; + if (map > 0x03) + map = 0; + break; + } + + if (map != 0) { + int width = xga->accel.px_map_width[map]; + int pos = xga_calc_pos(x, y, width); + uint32_t base = xga->accel.px_map_base[map]; + + ret = MASKED_READ(map, 1); + } + + return ret; +} + +static uint32_t +xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map) +{ + xga_t *xga = (xga_t *) svga->xga; + int width = xga->accel.px_map_width[map]; + int pos = xga_calc_pos(x, y, width); + uint32_t base = xga->accel.px_map_base[map]; + uint32_t ret = 0x00000000; switch (xga->accel.px_map_format[map] & 0x07) { - case 0: /*1-bit*/ - addr += (y * (width >> 3)); - addr += (x >> 3); - if (!skip) { - READ(addr, byte); - } else - byte = mem_readb_phys(addr); + case 0: /* 1 bpp */ + ret = MASKED_READ(map, 1); + break; - xga_log("1. AccessMode=%02x, SRCMAP=%02x, DSTMAP=%02x, PAT=%02x.\n", xga->access_mode & 0x0f, (xga->accel.px_map_format[xga->accel.src_map] & 0x0f), (xga->accel.px_map_format[xga->accel.dst_map] & 0x0f), xga->accel.pat_src); - if ((xga->accel.px_map_format[xga->accel.src_map] & 0x08) && !(xga->access_mode & 0x08)) - bits = (x & 7); - else - bits = 7 - (x & 7); + case 1: /* 2 bpp */ + ret = MASKED_READ(map, 2); + break; - px = (byte >> bits) & 1; - return px; - case 2: /*4-bit*/ - addr += (y * (width >> 1)); - addr += (x >> 1); - if (!skip) { - READ(addr, byte); - } else - byte = mem_readb_phys(addr); + case 2: /* 4 bpp */ + ret = MASKED_READ(map, 4); + break; - 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); - addr += x; - if (!skip) { - READ(addr, byte); - } else - byte = mem_readb_phys(addr); + case 3: /* 8 bpp */ + ret = READ_MAP(base, pos, map); + break; - return byte; - case 4: /*16-bit*/ - addr += (y * (width << 1)); - addr += (x << 1); - - 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; + case 4: /* 16 bpp */ + ret = READ_MAPW(base, pos, map); + break; default: break; } - return 0; + + return ret; } static void -xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, uint32_t pixel, int width) +xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t pixel) { xga_t *xga = (xga_t *) svga->xga; - uint32_t addr = base; uint8_t byte; uint8_t mask; - int skip = 0; - - if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) - skip = 1; + int bit; + int width = xga->accel.px_map_width[map]; + int pos = xga_calc_pos(x, y, width); + uint32_t base = xga->accel.px_map_base[map]; switch (xga->accel.px_map_format[map] & 0x07) { - case 0: /*1-bit*/ - addr += (y * (width >> 3)); - addr += (x >> 3); - if (!skip) { - READ(addr, byte); - } else - byte = mem_readb_phys(addr); + case 0: /* 1 bpp */ + byte = READ_MAP(base, pos, map); + bit = pos & 7; - if (xga->access_mode & 0x08) - mask = 1 << (7 - (x & 7)); - else { - if ((xga->accel.px_map_format[map] & 0x08) || (xga->accel.px_map_format[xga->accel.src_map] & 0x08)) { - xga_log("2. AccessMode=%02x, SRCMAP=%02x, DSTMAP=%02x, PAT=%02x.\n", xga->access_mode & 0x0f, (xga->accel.px_map_format[xga->accel.src_map] & 0x0f), (xga->accel.px_map_format[map] & 0x0f), xga->accel.pat_src); - mask = 1 << (x & 7); - } else - mask = 1 << (7 - (x & 7)); - } - - byte = (byte & ~mask) | ((pixel ? 0xff : 0) & mask); - if (pixel & 1) { - if (!skip) { - xga->vram[addr & (xga->vram_mask)] |= mask; - xga->changedvram[(addr & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; - } - } else { - if (!skip) { - xga->vram[addr & (xga->vram_mask)] &= ~mask; - xga->changedvram[(addr & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; - } - } - mem_writeb_phys(addr, byte); - break; - case 2: /*4-bit*/ - addr += (y * (width >> 1)); - addr += (x >> 1); - if (!skip) { - READ(addr, byte); - } else - byte = mem_readb_phys(addr); - - if (xga->accel.px_map_format[map] & 0x08) - mask = 0x0f << ((x & 1) << 2); - else - mask = 0x0f << ((1 - (x & 1)) << 2); + pixel <<= bit; + mask = 1 << bit; byte = (byte & ~mask) | (pixel & mask); - if (!skip) { - WRITE(addr, byte); - } - mem_writeb_phys(addr, byte); + WRITE_MAP(base, pos, map, byte); break; - case 3: /*8-bit*/ - addr += (y * width); - addr += x; - if (!skip) { - WRITE(addr, pixel & 0xff); - } - mem_writeb_phys(addr, pixel & 0xff); - break; - case 4: /*16-bit*/ - addr += (y * width << 1); - addr += (x << 1); - if (!skip) { - WRITEW(addr, pixel); - } else { - 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); + case 1: /* 2 bpp */ + byte = READ_MAP(base, pos, map); + mask = ((pos & 3) << 1); + + pixel <<= mask; + mask = 0x03 << mask; + + byte = (byte & ~mask) | (pixel & mask); + WRITE_MAP(base, pos, map, byte); + break; + + case 2: /* 4 bpp */ + byte = READ_MAP(base, pos, map); + mask = ((pos & 1) << 2); + + pixel <<= mask; + mask = 0x0f << mask; + + byte = (byte & ~mask) | (pixel & mask); + WRITE_MAP(base, pos, map, byte); + break; + + case 3: /* 8bpp */ + WRITE_MAP(base, pos, map, pixel); + break; + + case 4: /* 16bpp */ + WRITE_MAPW(base, pos, map, pixel); break; default: @@ -1171,8 +1236,6 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) uint32_t old_dest_dat; uint32_t color_cmp = xga->accel.color_cmp; uint32_t plane_mask = xga->accel.plane_mask; - uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map]; - uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; int y = ssv & 0x0f; int x = 0; int16_t dx; @@ -1230,8 +1293,11 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) while (y >= 0) { 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.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, + xga->accel.src_map_y & 0xfff, xga->accel.src_map) : + xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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; @@ -1239,19 +1305,22 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); if ((xga->accel.command & 0x30) == 0) { if (ssv & 0x10) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } else if (((xga->accel.command & 0x30) == 0x10) && x) { if (ssv & 0x10) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } else if (((xga->accel.command & 0x30) == 0x20) && y) { if (ssv & 0x10) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } } else { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, + xga->accel.src_map_y & 0xfff, xga->accel.src_map) : + xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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; @@ -1259,13 +1328,13 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); if ((xga->accel.command & 0x30) == 0) { if (ssv & 0x10) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } else if (((xga->accel.command & 0x30) == 0x10) && x) { if (ssv & 0x10) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } else if (((xga->accel.command & 0x30) == 0x20) && y) { if (ssv & 0x10) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } @@ -1294,8 +1363,6 @@ xga_line_draw_write(svga_t *svga) uint32_t old_dest_dat = 0x00000000; uint32_t color_cmp = xga->accel.color_cmp; uint32_t plane_mask = xga->accel.plane_mask; - uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map]; - 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; @@ -1316,7 +1383,7 @@ xga_line_draw_write(svga_t *svga) dy |= ~0x17ff; if ((xga->accel.command & 0x30) == 0x30) - 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); + 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, frgdmix=%02x, bkgdmix=%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, xga->accel.frgd_mix & 0x1f, xga->accel.bkgd_mix & 0x1f); if (xga->accel.pat_src == 8) { if ((xga->accel.command & 0x30) == 0x30) { @@ -1358,32 +1425,39 @@ xga_line_draw_write(svga_t *svga) 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map) : + xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } else { 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map) : + xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } - if (x == xga->accel.blt_width) + if (x == xga->accel.blt_width) { + xga->accel.dst_map_x = dx; + xga->accel.dst_map_y = dy; break; + } if (xga->accel.octant & 0x01) { if (xga->accel.octant & 0x02) @@ -1421,35 +1495,41 @@ xga_line_draw_write(svga_t *svga) while (y >= 0) { 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.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, + xga->accel.src_map_y & 0xfff, xga->accel.src_map) : + xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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); if ((xga->accel.command & 0x30) == 0) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); else if (((xga->accel.command & 0x30) == 0x10) && x) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); else if (((xga->accel.command & 0x30) == 0x20) && y) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } else { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, + xga->accel.src_map_y & 0xfff, xga->accel.src_map) : + xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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); if ((xga->accel.command & 0x30) == 0) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); else if (((xga->accel.command & 0x30) == 0x10) && x) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); else if (((xga->accel.command & 0x30) == 0x20) && y) - 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); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } @@ -1504,13 +1584,10 @@ 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; - 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]; + uint32_t patwidth; uint32_t dstwidth = xga->accel.px_map_width[xga->accel.dst_map]; uint32_t srcwidth = xga->accel.px_map_width[xga->accel.src_map]; - uint32_t patheight = xga->accel.px_map_height[xga->accel.pat_src]; + uint32_t patheight; uint32_t srcheight = xga->accel.px_map_height[xga->accel.src_map]; uint32_t dstheight = xga->accel.px_map_height[xga->accel.dst_map]; uint32_t frgdcol = xga->accel.frgd_color; @@ -1539,17 +1616,18 @@ xga_bitblt(svga_t *svga) xga->accel.pattern = 0; xga->accel.filling = 0; + xga->accel.y_len = 0; 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, frgdcol=%04x, bkgdcol=%04x, bgmix=%02x, fgmix=%02x.\n", + "usesrcvramfr=%d, usevrambk=%d, planemask=%04x, 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.pat_src & 0x03] & 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), - frgdcol, bkgdcol, xga->accel.bkgd_mix & 0x1f, xga->accel.frgd_mix & 0x1f); + xga->accel.plane_mask, frgdcol, bkgdcol, xga->accel.bkgd_mix & 0x1f, xga->accel.frgd_mix & 0x1f); if (xga->accel.pat_src == 8) { if (srcheight == 7) @@ -1559,43 +1637,43 @@ xga_bitblt(svga_t *svga) if ((xga->accel.dst_map == 1) && (xga->accel.src_map == 2)) { if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0a) && (xga->accel.px_map_format[xga->accel.src_map] >= 0x0a)) xga->accel.pattern = 1; + else if (!(xga->accel.px_map_format[xga->accel.dst_map] & 0x08) && !(xga->accel.px_map_format[xga->accel.src_map] & 0x08)) { + if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x02) && (xga->accel.px_map_format[xga->accel.src_map] >= 0x02)) + xga->accel.pattern = 1; + } } } } - xga_log("PAT8: PatFormat=%x, SrcFormat=%x, DstFormat=%x.\n", xga->accel.px_map_format[xga->accel.pat_src] & 8, (xga->accel.px_map_format[xga->accel.src_map]), (xga->accel.px_map_format[xga->accel.dst_map])); - xga_log("Pattern Map = 8: CMD = %08x: SRCBase = %08x, DSTBase = %08x, from/to vram dir = %d, " - "cmd dir = %06x\n", xga->accel.command, srcbase, dstbase, xga->from_to_vram, - xga->accel.dir_cmd); - xga_log("CMD = %08x: Y = %d, X = %d, patsrc = %02x, srcmap = %d, dstmap = %d, py = %d, " - "sy = %d, dy = %d, width0 = %d, width1 = %d, width2 = %d, width3 = %d\n", - xga->accel.command, xga->accel.y, xga->accel.x, xga->accel.pat_src, xga->accel.src_map, - xga->accel.dst_map, xga->accel.py, xga->accel.sy, dy, - xga->accel.px_map_width[0], xga->accel.px_map_width[1], - xga->accel.px_map_width[2], xga->accel.px_map_width[3]); - xga_log("PAT8: Pattern Enabled?=%d, xdir=%d, ydir=%d.\n", xga->accel.pattern, xdir, ydir); + xga_log("CMD=%08x, EnablePat=%d, SRC%d, DST%d: SrcFormat=%x, DstFormat=%x, SrcWidth=%d, SrcHeight=%d, DstWidth=%d, DstHeight=%d, sx=%d, sy=%d.\n", xga->accel.command, + xga->accel.pattern, xga->accel.src_map, xga->accel.dst_map, (xga->accel.px_map_format[xga->accel.src_map] & 0x0f), (xga->accel.px_map_format[xga->accel.dst_map] & 0x0f), + srcwidth, srcheight, dstwidth, dstheight, xga->accel.sx, xga->accel.sy); while (xga->accel.y >= 0) { 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; - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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, dstwidth + 1); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } 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; - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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, dstwidth + 1); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } @@ -1606,6 +1684,7 @@ xga_bitblt(svga_t *svga) xga->accel.sx += xdir; dx += xdir; + xga->accel.x--; if (xga->accel.x < 0) { xga->accel.x = xga->accel.blt_width & 0xfff; @@ -1616,6 +1695,7 @@ xga_bitblt(svga_t *svga) xga->accel.sx = xga->accel.src_map_x & 0xfff; dy += ydir; + xga->accel.y_len++; if (xga->accel.pattern) xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); @@ -1632,7 +1712,8 @@ xga_bitblt(svga_t *svga) } } } else if (xga->accel.pat_src >= 1) { - patbase = xga->accel.px_map_base[xga->accel.pat_src]; + patwidth = xga->accel.px_map_width[xga->accel.pat_src]; + patheight = xga->accel.px_map_height[xga->accel.pat_src]; if (patheight == 7) { if (xga->accel.src_map != 1) @@ -1649,38 +1730,31 @@ xga_bitblt(svga_t *svga) } else { if (!xga->accel.src_map && (xga->accel.dst_map == 1) && (xga->accel.pat_src == 2)) { if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x0a) && (xga->accel.px <= 7) && (xga->accel.py <= 3)) { - if ((patwidth >= 7) && ((xga->accel.command & 0xc0) == 0x40)) + if (patheight > 1) xga->accel.pattern = 0; else xga->accel.pattern = 1; + } else if (!(xga->accel.px_map_format[xga->accel.dst_map] & 0x08)) { + if ((xga->accel.px_map_format[xga->accel.dst_map] >= 0x02) && (xga->accel.px <= 7) && (xga->accel.py <= 3)) { + if (patheight > 1) + xga->accel.pattern = 0; + else + xga->accel.pattern = 1; + } } } } } } - xga_log("PAT%d: PatFormat=%x, SrcFormat=%x, DstFormat=%x.\n", xga->accel.pat_src, xga->accel.px_map_format[xga->accel.pat_src] & 8, (xga->accel.px_map_format[xga->accel.src_map]), (xga->accel.px_map_format[xga->accel.dst_map])); - xga_log("XGA bitblt linear endian reverse=%d, octanty=%d, src command = %08x, pxsrcmap=%x, " - "pxdstmap=%x, srcmap=%d, patmap=%d, dstmap=%d, dstwidth=%d, dstheight=%d, srcwidth=%d, " - "srcheight=%d, dstbase=%08x, srcbase=%08x.\n", xga->linear_endian_reverse, ydir, - xga->accel.command, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, - xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.src_map, - xga->accel.pat_src, xga->accel.dst_map, dstwidth, dstheight, srcwidth, srcheight, - dstbase, srcbase); - xga_log("Pattern Map = %d: CMD = %08x: PATBase = %08x, SRCBase = %08x, DSTBase = %08x\n", - xga->accel.pat_src, xga->accel.command, patbase, srcbase, dstbase); - xga_log("CMD = %08x: Y = %d, X = %d, patsrc = %02x, srcmap = %d, dstmap = %d, py = %d, " - "sy = %d, dy = %d, width0 = %d, width1 = %d, width2 = %d, width3 = %d, bkgdcol = %02x\n", - xga->accel.command, xga->accel.y, xga->accel.x, xga->accel.pat_src, - xga->accel.src_map, xga->accel.dst_map, xga->accel.py, xga->accel.sy, xga->accel.dy, - xga->accel.px_map_width[0], xga->accel.px_map_width[1], - 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); + xga_log("CMD=%08x, EnablePat=%d, PAT%d, SRC%d, DST%d: PatFormat=%x, SrcFormat=%x, DstFormat=%x, PatWidth=%d, PatHeight=%d, SrcWidth=%d, SrcHeight=%d, DstWidth=%d, DstHeight=%d, px=%d, py=%d.\n", xga->accel.command, + xga->accel.pattern, xga->accel.pat_src, xga->accel.src_map, xga->accel.dst_map, xga->accel.px_map_format[xga->accel.pat_src], (xga->accel.px_map_format[xga->accel.src_map] & 0x0f), (xga->accel.px_map_format[xga->accel.dst_map] & 0x0f), + patwidth, patheight, srcwidth, srcheight, dstwidth, dstheight, xga->accel.px, xga->accel.py); 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); + mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py); if (mix) xga->accel.filling ^= 1; @@ -1688,26 +1762,30 @@ xga_bitblt(svga_t *svga) 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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_log("1SRCDat=%02x, DSTDat=%02x, Old=%02x, MIX=%d.\n", src_dat, dest_dat, old_dest_dat, area_state); - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + xga_log("XGA Area Fill1: Dest=%02x, Src=%02x, OldD=%02x.\n", dest_dat, src_dat, old_dest_dat); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } 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); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + frgdcol; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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_log("2Fill: NumXY(%d,%d): DXY(%d,%d): SRCDat=%02x, DSTDat=%02x, Old=%02x, frgdcol=%02x, bkgdcol=%02x, MIX=%d, frgdmix=%02x, bkgdmix=%02x, dstmapfmt=%02x, srcmapfmt=%02x, srcmapnum=%d.\n", x, y, dx, dy, src_dat, dest_dat, old_dest_dat, frgdcol, bkgdcol, area_state, xga->accel.frgd_mix & 0x1f, xga->accel.bkgd_mix & 0x1f, xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.src_map); - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + xga_log("XGA Area Fill2: Dest=%02x, Src=%02x, OldD=%02x.\n", dest_dat, src_dat, old_dest_dat); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } @@ -1743,50 +1821,60 @@ 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); + mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py); 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 (mix) - 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; + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + frgdcol; else - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : bkgdcol; + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + bkgdcol; - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1); + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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(mix, 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, dstwidth + 1); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } else { if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { if (mix) - 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; + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + frgdcol; else - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : bkgdcol; + src_dat = (((xga->accel.command >> 30) & 3) == 2) ? + xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map) : + bkgdcol; - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1); + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map); 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(mix, 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, dstwidth + 1); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dest_dat); } } } xga->accel.sx += xdir; + if (xga->accel.pattern) xga->accel.px = ((xga->accel.px + xdir) & patwidth) | (xga->accel.px & ~patwidth); else xga->accel.px += xdir; + xga_log("MIX=%d, DX=%d, DY=%d, LX=%d, LY=%d, PX=%d, PY=%d, SX=%d, SY=%d.\n", mix, dx, dy, xga->accel.x, xga->accel.y, xga->accel.px, xga->accel.py, xga->accel.sx, xga->accel.sy); + dx += xdir; + xga->accel.x--; if (xga->accel.x < 0) { xga->accel.y--; @@ -1800,6 +1888,7 @@ xga_bitblt(svga_t *svga) xga->accel.px = xga->accel.pat_map_x & 0xfff; xga->accel.sy += ydir; + if (xga->accel.pattern) xga->accel.py = ((xga->accel.py + ydir) & patheight) | (xga->accel.py & ~patheight); else @@ -1850,6 +1939,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) break; case 0x14: + xga_log("MMIO14, len=%d, val=%08x, pxmapidx=%d.\n", len, val, xga->accel.px_map_idx); if (len == 4) xga->accel.px_map_base[xga->accel.px_map_idx] = val; else if (len == 2) @@ -1862,6 +1952,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0xffff00ff) | (val << 8); break; case 0x16: + xga_log("MMIO16, len=%d, val=%08x, pxmapidx=%d.\n", len, val, xga->accel.px_map_idx); if (len == 2) xga->accel.px_map_base[xga->accel.px_map_idx] = (xga->accel.px_map_base[xga->accel.px_map_idx] & 0x0000ffff) | (val << 16); else @@ -1878,10 +1969,12 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) xga->accel.px_map_height[xga->accel.px_map_idx] = (val >> 16) & 0xffff; } else if (len == 2) { xga->accel.px_map_width[xga->accel.px_map_idx] = val & 0xffff; + xga_log("MMIO18, len=2, val=%04x, pxmapidx=%d.\n", val & 0xffff, xga->accel.px_map_idx); } else xga->accel.px_map_width[xga->accel.px_map_idx] = (xga->accel.px_map_width[xga->accel.px_map_idx] & 0xff00) | val; break; case 0x19: + xga_log("MMIO19, len=%d, val=%08x.\n", len, val); if (len == 1) xga->accel.px_map_width[xga->accel.px_map_idx] = (xga->accel.px_map_width[xga->accel.px_map_idx] & 0xff) | (val << 8); break; @@ -2055,6 +2148,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) break; case 0x54: + xga_log("MMIO54, len=%d, val=%08x.\n", len, val); if (len == 4) xga->accel.carry_chain = val; else if (len == 2) @@ -2067,6 +2161,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) xga->accel.carry_chain = (xga->accel.carry_chain & 0xffff00ff) | (val << 8); break; case 0x56: + xga_log("MMIO56, len=%d, val=%04x.\n", len, val); if (len == 2) xga->accel.carry_chain = (xga->accel.carry_chain & 0x0000ffff) | (val << 16); else @@ -2260,13 +2355,12 @@ 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]); - if (xga->accel.pat_src) - xga_log("[%04X:%08X]: Accel Command = %02x, full = %08x, patwidth = %d, " + xga_log("[%04X:%08X]: Accel Command = %02x, full = %08x, patwidth = %d, " "dstwidth = %d, srcwidth = %d, patheight = %d, dstheight = %d, " "srcheight = %d, px = %d, py = %d, dx = %d, dy = %d, sx = %d, " "sy = %d, patsrc = %d, dstmap = %d, srcmap = %d, dstbase = %08x, " "srcbase = %08x, patbase = %08x, dstformat = %x, srcformat = %x, " - "planemask = %08x\n\n", + "planemask = %08x.\n", CS, cpu_state.pc, ((xga->accel.command >> 24) & 0x0f), xga->accel.command, xga->accel.px_map_width[xga->accel.pat_src], xga->accel.px_map_width[xga->accel.dst_map], @@ -2285,6 +2379,8 @@ exec_command: xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.plane_mask); + xga->src_reverse_order = 0; + xga->dst_reverse_order = 0; switch ((xga->accel.command >> 24) & 0x0f) { case 2: /*Short Stroke Vectors Read */ xga_log("Short Stroke Vectors Read.\n"); @@ -2300,14 +2396,14 @@ exec_command: xga_line_draw_write(svga); break; case 8: /*BitBLT*/ - xga_log("BitBLT.\n"); + xga_log("Normal BitBLT.\n"); xga_bitblt(svga); break; case 9: /*Inverting BitBLT*/ xga_log("Inverting BitBLT\n"); break; case 0x0a: /*Area Fill*/ - xga_log("Area Fill BitBLT.\n"); + xga_log("Area Fill.\n"); xga_bitblt(svga); break; @@ -2631,24 +2727,31 @@ xga_render_4bpp(svga_t *svga) if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; - xga->lastline_draw = xga->displine; - for (int x = 0; x <= xga->h_disp; x += 8) { + for (int x = 0; x <= xga->h_disp; x += 16) { 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->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[1] = xga->pallook[dat & 0x0f]; + p[0] = xga->pallook[(dat >> 4) & 0x0f]; + p[3] = xga->pallook[(dat >> 8) & 0x0f]; + p[2] = xga->pallook[(dat >> 12) & 0x0f]; + p[5] = xga->pallook[(dat >> 16) & 0x0f]; + p[4] = xga->pallook[(dat >> 20) & 0x0f]; p[7] = xga->pallook[(dat >> 24) & 0x0f]; + p[6] = xga->pallook[(dat >> 28) & 0x0f]; + + dat = *(uint32_t *) (&xga->vram[(xga->memaddr + 4) & xga->vram_mask]); + p[9] = xga->pallook[dat & 0x0f]; + p[8] = xga->pallook[(dat >> 4) & 0x0f]; + p[11] = xga->pallook[(dat >> 8) & 0x0f]; + p[10] = xga->pallook[(dat >> 12) & 0x0f]; + p[13] = xga->pallook[(dat >> 16) & 0x0f]; + p[12] = xga->pallook[(dat >> 20) & 0x0f]; + p[15] = xga->pallook[(dat >> 24) & 0x0f]; + p[14] = xga->pallook[(dat >> 28) & 0x0f]; xga->memaddr += 8; - p += 8; + p += 16; } xga->memaddr &= xga->vram_mask; } @@ -2771,13 +2874,20 @@ xga_write_banked(uint32_t addr, uint8_t val, void *priv) svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - if (xga->access_mode & 0x08) { - if ((xga->access_mode & 0x07) == 0x04) - addr ^= 1; - } + xga->changedvram[(xga_transform_addr(addr, xga->access_mode) & xga->vram_mask) >> 12] = + svga->monitor->mon_changeframecount; + xga->vram[xga_transform_addr(addr, xga->access_mode) & xga->vram_mask] = + xga_transform_val(val, xga->access_mode, 8); +} - xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; - xga->vram[addr & xga->vram_mask] = val; +static void +xga_writew_banked(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; + *(uint16_t *) &(xga->vram[addr & xga->vram_mask]) = xga_transform_val(val, xga->access_mode, 16); } static void @@ -2789,6 +2899,7 @@ xga_write(uint32_t addr, uint8_t val, void *priv) addr &= xga->banked_mask; addr += xga->write_bank; + xga_log("WriteBankedB addr=%08x, val=%02x, addrshift1=%08x.\n", addr, val, addr >> 1); if (addr >= xga->vram_size) return; @@ -2806,13 +2917,13 @@ xga_writew(uint32_t addr, uint16_t val, void *priv) addr &= xga->banked_mask; addr += xga->write_bank; + xga_log("WriteBankedW addr=%08x, val=%04x, addrshift1=%08x.\n", addr, val, addr >> 1); if (addr >= xga->vram_size) return; cycles -= svga->monitor->mon_video_timing_write_w; - xga_write_banked(addr, val & 0xff, svga); - xga_write_banked(addr + 1, val >> 8, svga); + xga_writew_banked(addr, val, svga); } static void @@ -2824,15 +2935,14 @@ xga_writel(uint32_t addr, uint32_t val, void *priv) addr &= xga->banked_mask; addr += xga->write_bank; + xga_log("WriteBankedL addr=%08x, val=%08x, addrshift1=%08x.\n", addr, val, addr >> 1); if (addr >= xga->vram_size) return; cycles -= svga->monitor->mon_video_timing_write_l; - xga_write_banked(addr, val & 0xff, svga); - xga_write_banked(addr + 1, val >> 8, svga); - xga_write_banked(addr + 2, val >> 16, svga); - xga_write_banked(addr + 3, val >> 24, svga); + xga_writew_banked(addr, val & 0xffff, svga); + xga_writew_banked(addr + 2, val >> 16, svga); } uint8_t @@ -2882,12 +2992,21 @@ xga_read_banked(uint32_t addr, void *priv) xga_t *xga = (xga_t *) svga->xga; uint8_t ret = 0xff; - if (xga->access_mode & 0x08) { - if ((xga->access_mode & 0x07) == 0x04) - addr ^= 1; - } + ret = xga_transform_val(xga->vram[xga_transform_addr(addr, xga->access_mode) & xga->vram_mask], + xga->access_mode, 8); - ret = xga->vram[addr & xga->vram_mask]; + return ret; +} + +static uint16_t +xga_readw_banked(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint16_t ret = 0xffff; + + ret = xga_transform_val(*(uint16_t *) &(xga->vram[addr & xga->vram_mask]), + xga->access_mode, 16); return ret; } @@ -2930,8 +3049,7 @@ xga_readw(uint32_t addr, void *priv) cycles -= svga->monitor->mon_video_timing_read_w; - ret = xga_read_banked(addr, svga); - ret |= (xga_read_banked(addr + 1, svga) << 8); + ret = xga_readw_banked(addr, svga); return ret; } @@ -2952,10 +3070,8 @@ xga_readl(uint32_t addr, void *priv) cycles -= svga->monitor->mon_video_timing_read_l; - ret = xga_read_banked(addr, svga); - ret |= (xga_read_banked(addr + 1, svga) << 8); - ret |= (xga_read_banked(addr + 2, svga) << 16); - ret |= (xga_read_banked(addr + 3, svga) << 24); + ret = xga_readw_banked(addr, svga); + ret |= (xga_readw_banked(addr + 2, svga) << 16); return ret; } @@ -2965,13 +3081,13 @@ 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("WriteLL XGA=%d.\n", xga->on); + xga_log("WriteLL XGA=%d, addr=%08x, val=%02x.\n", xga->on, addr, val); if (!xga->on) { svga_write_linear(addr, val, svga); return; } - addr &= (xga->vram_size - 1); + addr &= xga->vram_mask; if (addr >= xga->vram_size) { xga_log("Write Linear Over!.\n"); @@ -2980,23 +3096,35 @@ xga_write_linear(uint32_t addr, uint8_t val, void *priv) cycles -= svga->monitor->mon_video_timing_write_b; - xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; - xga->vram[addr & xga->vram_mask] = val; + xga->changedvram[(xga_transform_addr(addr, xga->access_mode) & xga->vram_mask) >> 12] = + svga->monitor->mon_changeframecount; + xga->vram[xga_transform_addr(addr, xga->access_mode) & xga->vram_mask] = + xga_transform_val(val, xga->access_mode, 8); } static void xga_writew_linear(uint32_t addr, uint16_t val, void *priv) { - svga_t *svga = (svga_t *) priv; - const xga_t *xga = (xga_t *) svga->xga; + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + xga_log("WriteLL XGA=%d, addr=%08x, val=%02x.\n", xga->on, addr, val); if (!xga->on) { svga_writew_linear(addr, val, svga); return; } - xga_write_linear(addr, val, priv); - xga_write_linear(addr + 1, val >> 8, priv); + addr &= xga->vram_mask; + + if (addr >= xga->vram_size) { + xga_log("Write Linear Over!.\n"); + return; + } + + cycles -= svga->monitor->mon_video_timing_write_b; + + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; + *(uint16_t *) &(xga->vram[addr & xga->vram_mask]) = xga_transform_val(val, xga->access_mode, 16); } static void @@ -3010,10 +3138,8 @@ xga_writel_linear(uint32_t addr, uint32_t val, void *priv) return; } - xga_write_linear(addr, val, priv); - xga_write_linear(addr + 1, val >> 8, priv); - xga_write_linear(addr + 2, val >> 16, priv); - xga_write_linear(addr + 3, val >> 24, priv); + xga_writew_linear(addr, val, priv); + xga_writew_linear(addr + 2, val >> 16, priv); } static uint8_t @@ -3023,19 +3149,17 @@ xga_read_linear(uint32_t addr, void *priv) const xga_t *xga = (xga_t *) svga->xga; uint8_t ret = 0xff; - if (!xga->on) - return svga_read_linear(addr, svga); + if (xga->on) { + addr &= xga->vram_mask; - addr &= (xga->vram_size - 1); + if (addr < xga->vram_size) { + cycles -= svga->monitor->mon_video_timing_read_b; - if (addr >= xga->vram_size) { - xga_log("Read Linear Over ADDR=%x!.\n", addr); - return ret; - } - - cycles -= svga->monitor->mon_video_timing_read_b; - - ret = xga->vram[addr & xga->vram_mask]; + ret = xga_transform_val(xga->vram[xga_transform_addr(addr, xga->access_mode) & xga->vram_mask], + xga->access_mode, 8); + } + } else + ret = svga_read_linear(addr, svga); return ret; } @@ -3045,13 +3169,19 @@ xga_readw_linear(uint32_t addr, void *priv) { svga_t *svga = (svga_t *) priv; const xga_t *xga = (xga_t *) svga->xga; - uint16_t ret; + uint16_t ret = 0xffff; - if (!xga->on) - return svga_readw_linear(addr, svga); + if (xga->on) { + addr &= xga->vram_mask; - ret = xga_read_linear(addr, svga); - ret |= (xga_read_linear(addr + 1, svga) << 8); + if (addr < xga->vram_size) { + cycles -= svga->monitor->mon_video_timing_read_b; + + ret = xga_transform_val(*(uint16_t *) &(xga->vram[addr & xga->vram_mask]), + xga->access_mode, 16); + } + } else + ret = svga_readw_linear(addr, svga); return ret; } @@ -3066,10 +3196,8 @@ xga_readl_linear(uint32_t addr, void *priv) if (!xga->on) return svga_readl_linear(addr, svga); - ret = xga_read_linear(addr, svga); - ret |= (xga_read_linear(addr + 1, svga) << 8); - ret |= (xga_read_linear(addr + 2, svga) << 16); - ret |= (xga_read_linear(addr + 3, svga) << 24); + ret = xga_readw_linear(addr, svga); + ret |= (xga_readw_linear(addr + 2, svga) << 16); return ret; } @@ -3121,10 +3249,10 @@ xga_poll(void *priv) svga->render_xga(svga); - svga->x_add = (overscan_x >> 1); + svga->x_add = svga->left_overscan; xga_render_overscan_left(xga, svga); xga_render_overscan_right(xga, svga); - svga->x_add = (overscan_x >> 1); + svga->x_add = svga->left_overscan; if (xga->hwcursor_on) { xga_hwcursor_draw(svga, xga->displine + svga->y_add); @@ -3229,11 +3357,11 @@ xga_poll(void *priv) } if (xga->vc == xga->v_total) { xga->vc = 0; - xga->scanline = 0; + xga->scanline = 0; xga->dispon = 1; xga->displine = (xga->interlace && xga->oddeven) ? 1 : 0; - svga->x_add = (overscan_x >> 1); + svga->x_add = svga->left_overscan; xga->hwcursor_on = 0; xga->hwcursor_latch = xga->hwcursor; @@ -3273,14 +3401,14 @@ xga_mca_write(int port, uint8_t val, void *priv) /* Save the MCA register value. */ xga->pos_regs[port & 7] = val; - if (!(xga->pos_regs[4] & 1)) /*MCA 4MB addressing on systems with more than 16MB of memory*/ - xga->pos_regs[4] |= 1; if (xga->pos_regs[2] & 1) { xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); + if (!xga->base_addr_1mb) + xga->pos_regs[4] |= 1; /*If 1MB VRAM aperture is disabled on MCA, enable the 4MB VRAM aperture instead.*/ io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); @@ -3361,7 +3489,6 @@ xga_pos_in(uint16_t addr, void *priv) ret = xga->pos_regs[3]; ret |= (xga->dma_channel << 3); } - xga_log("POS IDX for 0103 = %d, ret = %02x.\n", xga->pos_idx & 3, ret); break; case 0x0104: @@ -3465,11 +3592,8 @@ xga_pos_out(uint16_t addr, uint8_t val, void *priv) break; case 0x0104: xga_log("104Write=%02x.\n", val); - if ((xga->pos_idx & 3) == 0) { + if ((xga->pos_idx & 3) == 0) xga->pos_regs[4] = val; - if (!(xga->pos_regs[4] & 0x01)) /*4MB addressing on systems with more than 15MB of memory*/ - xga->pos_regs[4] |= 0x01; - } break; case 0x0105: xga_log("105Write=%02x.\n", val); @@ -3515,13 +3639,11 @@ xga_init(const device_t *info) svga->xga = xga; - xga->ext_mem_addr = device_get_config_hex16("ext_mem_addr"); - xga->instance_isa = device_get_config_int("instance"); xga->type = device_get_config_int("type"); xga->dma_channel = device_get_config_int("dma"); xga->bus = info->flags; - xga->vram_size = (1024 << 10); + xga->vram_size = 1024 << 10; xga->vram_mask = xga->vram_size - 1; xga->vram = calloc(xga->vram_size, 1); xga->changedvram = calloc((xga->vram_size >> 12) + 1, 1); @@ -3548,25 +3670,6 @@ xga_init(const device_t *info) mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, xga_memio_writeb, xga_memio_writew, xga_memio_writel, xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); - } else { - xga->pos_regs[2] = (xga->instance_isa << 1) | xga->ext_mem_addr; - xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); - xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; - xga->pos_regs[2] |= 0x01; - xga->pos_regs[4] |= 0x01; - if (mem_size >= 15360) - xga->pos_regs[5] = 0; - else { - xga->pos_regs[5] = ((mem_size * 64) >> 0x10) + 1; - if (xga->pos_regs[5] == 0x10) - xga->pos_regs[5] = 0x00; - } - xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; - xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); - rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, xga->rom_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, - xga_memio_writeb, xga_memio_writew, xga_memio_writel, - xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); } } @@ -3585,10 +3688,6 @@ xga_init(const device_t *info) } else { io_sethandler(0x0096, 0x0001, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); io_sethandler(0x0100, 0x0010, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); - if (xga_standalone_enabled) { - io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr, 0x2000); - } } return svga; } @@ -3678,89 +3777,6 @@ static const device_config_t xga_mca_configuration[] = { // clang-format on }; -static const device_config_t xga_isa_configuration[] = { - // clang-format off - { - .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 = 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 }, - { .description = "3 (2130h-213Fh)", .value = 3 }, - { .description = "4 (2140h-214Fh)", .value = 4 }, - { .description = "5 (2150h-215Fh)", .value = 5 }, - { .description = "6 (2160h-216Fh)", .value = 6 }, - { .description = "7 (2170h-217Fh)", .value = 7 }, - { .description = "" } - }, - .bios = { { 0 } } - }, - { - .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 }, - { .description = "CE00h", .value = 0x0070 }, - { .description = "D000h", .value = 0x0080 }, - { .description = "D200h", .value = 0x0090 }, - { .description = "D400h", .value = 0x00a0 }, - { .description = "D600h", .value = 0x00b0 }, - { .description = "D800h", .value = 0x00c0 }, - { .description = "DA00h", .value = 0x00d0 }, - { .description = "DC00h", .value = 0x00e0 }, - { .description = "DE00h", .value = 0x00f0 }, - { .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 -}; - static const device_config_t xga_inmos_isa_configuration[] = { // clang-format off { @@ -3812,20 +3828,6 @@ const device_t xga_device = { .config = xga_mca_configuration }; -const device_t xga_isa_device = { - .name = "XGA (ISA)", - .internal_name = "xga_isa", - .flags = DEVICE_ISA16, - .local = 0, - .init = xga_init, - .close = xga_close, - .reset = xga_reset, - .available = xga_available, - .speed_changed = xga_speed_changed, - .force_redraw = xga_force_redraw, - .config = xga_isa_configuration -}; - const device_t inmos_isa_device = { .name = "INMOS XGA (ISA)", .internal_name = "inmos_xga_isa", @@ -3848,6 +3850,4 @@ xga_device_add(void) if (machine_has_bus(machine, MACHINE_BUS_MCA)) device_add(&xga_device); - else - device_add(&xga_isa_device); }