From bc24fefee810e78cfd7d6f9269e9eabc6893535f Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 19 Jul 2025 13:34:51 +0200 Subject: [PATCH 1/5] Ported the latest changes of the ESP code from QEMU to 86box (July 19th, 2025) --- src/scsi/scsi_pcscsi.c | 187 ++++++++++++++++++++++++++++------------- 1 file changed, 128 insertions(+), 59 deletions(-) diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 7c991bdb1..1b1f6113d 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -54,6 +54,12 @@ #define ESP_FIFO_SZ 16 #define ESP_CMDFIFO_SZ 32 +enum ESPASCMode { + ESP_ASC_MODE_DIS = 0, /* Disconnected */ + ESP_ASC_MODE_INI = 1, /* Initiator */ + ESP_ASC_MODE_TGT = 2 /* Target */ +}; + #define ESP_TCLO 0x0 #define ESP_TCMID 0x1 #define ESP_FIFO 0x2 @@ -80,6 +86,13 @@ #define CMD_DMA 0x80 #define CMD_CMD 0x7f +#define CMD_GRP_MASK 0x70 + +#define CMD_GRP_MISC 0x00 +#define CMD_GRP_INIT 0x01 +#define CMD_GRP_TRGT 0x02 +#define CMD_GRP_DISC 0x04 + #define CMD_NOP 0x00 #define CMD_FLUSH 0x01 #define CMD_RESET 0x02 @@ -114,7 +127,7 @@ #define INTR_FC 0x08 #define INTR_BS 0x10 #define INTR_DC 0x20 -#define INTR_ILL 0x40 +#define INTR_IL 0x40 #define INTR_RST 0x80 #define SEQ_0 0x0 @@ -176,6 +189,7 @@ typedef struct esp_t { uint8_t id, lun; Fifo8 cmdfifo; uint8_t cmdfifo_cdb_offset; + uint8_t asc_mode; int data_ready; int32_t xfer_counter; @@ -435,12 +449,14 @@ esp_select(esp_t *dev) esp_log("ESP SCSI no devices on ID %d, LUN %d\n", dev->id, dev->lun); /* No such drive */ dev->rregs[ESP_RSTAT] = 0; + dev->asc_mode = ESP_ASC_MODE_DIS; dev->rregs[ESP_RINTR] = INTR_DC; esp_raise_irq(dev); return -1; } else esp_log("ESP SCSI device present on ID %d, LUN %d\n", dev->id, dev->lun); + dev->asc_mode = ESP_ASC_MODE_INI; return 0; } @@ -460,9 +476,10 @@ esp_transfer_data(esp_t *dev) * Initial incoming data xfer is complete for sequencer command * so raise deferred bus service and function complete interrupt */ - dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); - dev->rregs[ESP_RSEQ] = SEQ_CD; - break; + dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); + dev->rregs[ESP_RSEQ] = SEQ_CD; + esp_raise_irq(dev); + break; case CMD_SELATNS: case (CMD_SELATNS | CMD_DMA): @@ -470,22 +487,26 @@ esp_transfer_data(esp_t *dev) * Initial incoming data xfer is complete so raise command * completion interrupt */ - dev->rregs[ESP_RINTR] |= INTR_BS; - dev->rregs[ESP_RSEQ] = SEQ_MO; - break; + dev->rregs[ESP_RINTR] |= INTR_BS; + dev->rregs[ESP_RSEQ] = SEQ_MO; + esp_raise_irq(dev); + break; case CMD_TI: case (CMD_TI | CMD_DMA): /* - * Bus service interrupt raised because of initial change to - * DATA phase + * If the final COMMAND phase data was transferred using a TI + * command, clear ESP_CMD to terminate the TI command and raise + * the completion interrupt */ dev->rregs[ESP_CMD] = 0; dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + break; + + default: break; } - - esp_raise_irq(dev); } /* @@ -574,6 +595,7 @@ esp_do_message_phase(esp_t *dev) /* We only support LUN 0 */ esp_log("LUN = %i\n", dev->lun); dev->rregs[ESP_RSTAT] = 0; + dev->asc_mode = ESP_ASC_MODE_DIS; dev->rregs[ESP_RINTR] = INTR_DC; dev->rregs[ESP_RSEQ] = SEQ_0; esp_raise_irq(dev); @@ -631,6 +653,7 @@ esp_hard_reset(esp_t *dev) fifo8_reset(&dev->cmdfifo); dev->dma = 0; dev->tchi_written = 0; + dev->asc_mode = ESP_ASC_MODE_DIS; dev->rregs[ESP_CFG1] = dev->mca ? dev->HostID : 7; esp_log("ESP Reset\n"); @@ -686,18 +709,20 @@ esp_do_dma(esp_t *dev) switch (esp_get_phase(dev)) { case STAT_MO: len = MIN(len, fifo8_num_free(&dev->cmdfifo)); - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < len) { - int val = dma_channel_read(dev->DmaChannel); - buf[dev->dma_86c01.pos++] = val & 0xff; - } - dev->dma_86c01.pos = 0; - dma_set_drq(dev->DmaChannel, 0); - } else - esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE); + if (len) { + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + int val = dma_channel_read(dev->DmaChannel); + buf[dev->dma_86c01.pos++] = val & 0xff; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE); - esp_set_tc(dev, esp_get_tc(dev) - len); + esp_set_tc(dev, esp_get_tc(dev) - len); + } fifo8_push_all(&dev->cmdfifo, buf, len); dev->cmdfifo_cdb_offset += len; @@ -745,19 +770,21 @@ esp_do_dma(esp_t *dev) case STAT_CD: len = MIN(len, fifo8_num_free(&dev->cmdfifo)); - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < len) { - int val = dma_channel_read(dev->DmaChannel); - buf[dev->dma_86c01.pos++] = val & 0xff; - } - dev->dma_86c01.pos = 0; - dma_set_drq(dev->DmaChannel, 0); - } else - esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE); + if (len) { + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + int val = dma_channel_read(dev->DmaChannel); + buf[dev->dma_86c01.pos++] = val & 0xff; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE); - fifo8_push_all(&dev->cmdfifo, buf, len); - esp_set_tc(dev, esp_get_tc(dev) - len); + fifo8_push_all(&dev->cmdfifo, buf, len); + esp_set_tc(dev, esp_get_tc(dev) - len); + } dev->ti_size = 0; if (esp_get_tc(dev) == 0) { /* Command has been received */ @@ -775,20 +802,22 @@ esp_do_dma(esp_t *dev) switch (dev->rregs[ESP_CMD]) { case (CMD_TI | CMD_DMA): - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < len) { - int val = dma_channel_read(dev->DmaChannel); - esp_log("ESP SCSI DMA write for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff); - sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff; - dev->dma_86c01.pos++; - } - dma_set_drq(dev->DmaChannel, 0); - dev->dma_86c01.pos = 0; - } else - esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, WRITE_TO_DEVICE); + if (len) { + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + int val = dma_channel_read(dev->DmaChannel); + esp_log("ESP SCSI DMA write for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff); + sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff; + dev->dma_86c01.pos++; + } + dma_set_drq(dev->DmaChannel, 0); + dev->dma_86c01.pos = 0; + } else + esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, WRITE_TO_DEVICE); - esp_set_tc(dev, esp_get_tc(dev) - len); + esp_set_tc(dev, esp_get_tc(dev) - len); + } dev->buffer_pos += len; dev->xfer_counter -= len; dev->ti_size += len; @@ -834,18 +863,19 @@ esp_do_dma(esp_t *dev) switch (dev->rregs[ESP_CMD]) { case (CMD_TI | CMD_DMA): - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < len) { - dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); - esp_log("ESP SCSI DMA read for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); - dev->dma_86c01.pos++; - } - dev->dma_86c01.pos = 0; - dma_set_drq(dev->DmaChannel, 0); - } else - esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, READ_FROM_DEVICE); - + if (len) { + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); + esp_log("ESP SCSI DMA read for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); + dev->dma_86c01.pos++; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, READ_FROM_DEVICE); + } dev->buffer_pos += len; dev->xfer_counter -= len; dev->ti_size -= len; @@ -886,6 +916,7 @@ esp_do_dma(esp_t *dev) if (len) { buf[0] = dev->status; + /* Length already non-zero */ if (dev->mca) { dma_set_drq(dev->DmaChannel, 1); while (dev->dma_86c01.pos < len) { @@ -925,6 +956,7 @@ esp_do_dma(esp_t *dev) if (len) { buf[0] = 0; + /* Length already non-zero */ if (dev->mca) { dma_set_drq(dev->DmaChannel, 1); while (dev->dma_86c01.pos < len) { @@ -1323,6 +1355,37 @@ esp_callback(void *priv) } } +static int +esp_cmd_is_valid(esp_t *dev, uint8_t cmd) +{ + uint8_t cmd_group = (cmd & CMD_GRP_MASK) >> 4; + + /* Always allow misc commands */ + if (cmd_group == CMD_GRP_MISC) + return 1; + + switch (dev->asc_mode) { + case ESP_ASC_MODE_DIS: + /* Disconnected mode: only allow disconnected commands */ + if (cmd_group == CMD_GRP_DISC) + return 1; + + break; + + case ESP_ASC_MODE_INI: + /* Initiator mode: allow initiator commands */ + if (cmd_group == CMD_GRP_INIT) + return 1; + + break; + + default: + break; + } + + return 0; +} + static uint32_t esp_reg_read(esp_t *dev, uint32_t saddr) { @@ -1385,6 +1448,11 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) break; case ESP_CMD: dev->rregs[ESP_CMD] = val; + if (!esp_cmd_is_valid(dev, dev->rregs[saddr])) { + dev->rregs[ESP_RSTAT] |= INTR_IL; + esp_raise_irq(dev); + break; + } if (val & CMD_DMA) { dev->dma = 1; @@ -1446,6 +1514,7 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) handle_satn_stop(dev); break; case CMD_MSGACC: + dev->asc_mode = ESP_ASC_MODE_DIS; dev->rregs[ESP_RINTR] |= INTR_DC; dev->rregs[ESP_RSEQ] = 0; dev->rregs[ESP_RFLAGS] = 0; From a633bb40dfcc7477fb2597dd926723c0fc7127ba Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 20 Jul 2025 18:05:23 +0600 Subject: [PATCH 2/5] Fix FCHS recompiling for x64 dynarecs --- src/codegen/codegen_ops_x86-64.h | 24 ++++++++++++++----- src/codegen_new/codegen_backend_x86-64_uops.c | 7 +++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index 129d9a740..5d6a62c7a 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -3875,19 +3875,31 @@ FP_LOAD_IMM_Q(uint64_t v) static __inline void FP_FCHS(void) { + addbyte(0x48); /* MOVABS RAX, 0x8000000000000000 */ + addbyte(0xb8); + addquad(0x8000000000000000); + addbyte(0x66); /* MOVQ XMM15, RAX */ + addbyte(0x4c); + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xf8); + addbyte(0x48); /* XOR RAX, RAX */ + addbyte(0x31); + addbyte(0xc0); addbyte(0x8b); /*MOV EAX, TOP*/ addbyte(0x45); addbyte((uint8_t) cpu_state_offset(TOP)); - addbyte(0xf2); /*SUBSD XMM0, XMM0*/ + addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ addbyte(0x0f); - addbyte(0x5c); - addbyte(0xc0); - addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/ - addbyte(0x0f); - addbyte(0x5c); + addbyte(0x7e); addbyte(0x44); addbyte(0xc5); addbyte((uint8_t) cpu_state_offset(ST)); + addbyte(0x66); /* PXOR XMM0, XMM15 */ + addbyte(0x41); + addbyte(0x0F); + addbyte(0xEF); + addbyte(0xC7); addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ addbyte(0x64); addbyte(0x05); diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index 6b68434a0..356c8bcde 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -636,9 +636,10 @@ codegen_FCHS(codeblock_t *block, uop_t *uop) int src_size_a = IREG_GET_SIZE(uop->src_reg_a_real); if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) { - host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a); - host_x86_PXOR_XREG_XREG(block, dest_reg, dest_reg); - host_x86_SUBSD_XREG_XREG(block, dest_reg, REG_XMM_TEMP); + host_x86_MOVQ_XREG_XREG(block, dest_reg, src_reg_a); + host_x86_MOV64_REG_IMM(block, REG_RCX, 0x8000000000000000); + host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RCX); + host_x86_PXOR_XREG_XREG(block, dest_reg, REG_XMM_TEMP); } # ifdef RECOMPILER_DEBUG else From 174e92dad92d7c86b16ce1c3ca53db37a4968abe Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 20 Jul 2025 15:19:57 +0200 Subject: [PATCH 3/5] Correct the write activity indicator icon. --- src/qt/icons/write_active.ico | Bin 6950 -> 9622 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/qt/icons/write_active.ico b/src/qt/icons/write_active.ico index babf8c86c0f94585cf9e00cd60d17c682fcf7c34..dcd758ee6c6a6a76b60aa2fd3163206979f59f7c 100644 GIT binary patch literal 9622 zcmZQzU}Run5D);-3Je)63=D1z3=AS75dID}28MMk3=9$y5Pk;zd{)giMoG9*vrZ9Cjc!CE*8& z6-<(}@)Z#$5Vs(w6Brw&W|STcfzc2cY$4F_|Nno6dfXT!k6B9K76H{;5)2Fs21xDW z1Wug3My{uDv2kj~F99om2+^e0XE0kKVE`(JabZZAIBNcA_`uQ(GEJZK1F;1+NnU*q z^9P~41(JuU9i>M@U^E0qLtr!nKq1gz|NlROJYft{hr9H~Edy$YfyO8uklJAlpn*$} z<(L>(+Y6sKrYU5Jfa(ZxFuCn2bVowM5LX)on>c0dx>5U4Ltr%gK_P%Go#7H2O@E;B zVl@Aw<|A@>pwx$$Bf^#Dki}_{{vfU(o}{ebf*w|&^h7E~H)E7P8UmvsFd71*Aut*O cqaiRF0z)GN8kqn8XJ8~9gY*&KTEndp0InsfIRF3v literal 6950 zcmZQzU}RunkdRa-s|j8Vn2!AR`PIK<06PBpDo-z!ZdF1WSO~|NsAI@bLK0(AW2$fq?;p!NQ}& zXb6mkzz7WiCM19y1Wb%9Fo0Z|Fbo}WMi@YKKMwyQ`+by+B?Q?2Gcb^VL3Ir&7*vme zsy+vBbp@%%7+8?pFi;t^kdOaU2te%=P?sFkR$*j-wo^cD6PN=*Y!GJn z&j4!wAo|-d1*7z62#kina1Q}^4GLvIYcwd2g@p-RMleyp2i2cQ`XLs;%^PS2cz6*s z#E1j`|IfgH4};2C&`>9chLy7uz+nbWIUqI&gDe7>1rq)bDsw?2oBtUO95}%6|HlW0 z>#u(?T=`!QQpNB{yNf|fYbkgPl!b+bfrA57e*b3>6cl6-6BA>Qk&$6gQc_~j)YN1! zHa2Fkw6tV!a<u_4Q>44Gm>TNJwBvOG{%YC@5fPXlP*Q>FHsZGGz+G%$YM8mMmGq zux8B~hHcxnf$ctX<_yD?D_0n9-MYo_;K2iiH*elB{P^*M;rH*~;CjKBfq@~7fq`Kr z0|Ubu*l4UV1B0_D#>NaYjg1-37#lPEhdRzU&6puA&6r_knlZzf zG-HPUPzM{&G-gPfY0NNlrZK~rnZ^wNp`I{4W6Y3t#+YH|8DoYsXN(#CLp^5v-y{Ph&XqKaJr(G=M=NlEyF-49_skWcUw?G2@vG#>O)l(u`*^ z%ru_KaK?Bh!+&T*7^lr-NK2c^Ff(l?!S7T|DllziWyLd%w#wN zhW|k+$M_6`vGEy(G~+W2GmXzMoH0Jb@E;oa#%X65($dZ_%uGAOa3<{x!+&UkFrIma zA#LUvhM6`A|1%8# zp$Q3;LO?MC3XwCQwhkzV8UJT6HvZ3$X8fOFrtyDSv zoJsr7@E@88jc5L6NSpbeVdl*L3}{xkfCCRXGB z{~6N$|7V!_|3AZ-|Nj~I`S~yaFB~AGc-cV(1Oo#DFTKUsApqH4Ebc?NYG|_< Date: Mon, 21 Jul 2025 01:20:54 +0600 Subject: [PATCH 4/5] Write-protected indicator (part 1) --- src/config.c | 18 +++++++++++++++ src/floppy/fdd.c | 1 + src/include/86box/machine_status.h | 1 + src/include/86box/ui.h | 1 + src/qt/icons/write_protected.ico | Bin 0 -> 9622 bytes src/qt/qt_iconindicators.cpp | 8 ++++--- src/qt/qt_iconindicators.hpp | 2 ++ src/qt/qt_machinestatus.cpp | 34 +++++++++++++++++++++++++---- src/qt/qt_mediamenu.cpp | 7 +++++- src/qt/qt_ui.cpp | 28 ++++++++++++++++++++++++ src/qt_resources.qrc | 1 + src/unix/unix.c | 5 +++++ 12 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/qt/icons/write_protected.ico diff --git a/src/config.c b/src/config.c index acfbec758..95362bc06 100644 --- a/src/config.c +++ b/src/config.c @@ -1517,6 +1517,9 @@ load_other_removable_devices(void) sprintf(temp, "zip_%02i_image_path", c + 1); p = ini_section_get_string(cat, temp, ""); + + sprintf(temp, "zip_%02i_writeprot", c + 1); + zip_drives[c].read_only = ini_section_get_int(cat, temp, 0); if (!strcmp(p, usr_path)) p[0] = 0x00; @@ -1630,6 +1633,9 @@ load_other_removable_devices(void) sprintf(temp, "mo_%02i_image_path", c + 1); p = ini_section_get_string(cat, temp, ""); + sprintf(temp, "mo_%02i_writeprot", c + 1); + mo_drives[c].read_only = ini_section_get_int(cat, temp, 0); + if (!strcmp(p, usr_path)) p[0] = 0x00; @@ -3090,6 +3096,12 @@ save_other_removable_devices(void) sprintf(temp, "zip_%02i_scsi_id", c + 1); ini_section_delete_var(cat, temp); + sprintf(temp, "zip_%02i_writeprot", c + 1); + if (zip_drives[c].read_only) + ini_section_set_int(cat, temp, zip_drives[c].read_only); + else + ini_section_delete_var(cat, temp); + sprintf(temp, "zip_%02i_scsi_location", c + 1); if (zip_drives[c].bus_type != ZIP_BUS_SCSI) ini_section_delete_var(cat, temp); @@ -3146,6 +3158,12 @@ save_other_removable_devices(void) sprintf(temp, "mo_%02i_scsi_id", c + 1); ini_section_delete_var(cat, temp); + sprintf(temp, "mo_%02i_writeprot", c + 1); + if (mo_drives[c].read_only) + ini_section_set_int(cat, temp, mo_drives[c].read_only); + else + ini_section_delete_var(cat, temp); + sprintf(temp, "mo_%02i_scsi_location", c + 1); if (mo_drives[c].bus_type != MO_BUS_SCSI) ini_section_delete_var(cat, temp); diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 1623f932a..b5eb8c8fc 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -483,6 +483,7 @@ fdd_load(int drive, char *fn) drive_empty[drive] = 0; fdd_forced_seek(drive, 0); fdd_changed[drive] = 1; + ui_sb_update_icon_wp(SB_FLOPPY | drive, ui_writeprot[drive]); return; } c++; diff --git a/src/include/86box/machine_status.h b/src/include/86box/machine_status.h index e6e9e6acd..66805e653 100644 --- a/src/include/86box/machine_status.h +++ b/src/include/86box/machine_status.h @@ -5,6 +5,7 @@ typedef struct dev_status_empty_active_t { atomic_bool_t empty; atomic_bool_t active; atomic_bool_t write_active; + atomic_bool_t write_prot; } dev_status_empty_active_t; typedef struct dev_status_active_t { diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index 783400ebc..f4efd6ec1 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -67,6 +67,7 @@ extern void ui_sb_update_tip(int meaning); extern void ui_sb_update_icon(int tag, int active); extern void ui_sb_update_icon_write(int tag, int write); extern void ui_sb_update_icon_state(int tag, int state); +extern void ui_sb_update_icon_wp(int tag, int state); extern void ui_sb_set_text_w(wchar_t *wstr); extern void ui_sb_set_text(char *str); extern void ui_sb_bugui(char *str); diff --git a/src/qt/icons/write_protected.ico b/src/qt/icons/write_protected.ico new file mode 100644 index 0000000000000000000000000000000000000000..f867ab37362e7f17805498b644bff51767006325 GIT binary patch literal 9622 zcmZQzU}Run5D);-3Je)63=D1z3=AS75dID}28MMk3=9$y5Pk3?-rbhS>`($HC@-%m86fT>!!$carKxsCl4b5mYxJ(#7yBpOtAK~G2#|Y-#RvcY{|~BB z8R|i83J3=APlD?9|Ns9#{{R0!sNRxbU|=vnY9A+XlHssXEu$eY8UmvsF!VzJQWwGM zCsdkJ-$D9yp!ywF&m+?iyU4Qx){ektHmKeQ)&C3)Fu##*2h4nA_afT`uDi)-ufSXa zZD*jgTR>)lFv#s74DtuLVFWcFRCl7cV_si zibuE!ptcI7?H!n5AhQ}lVGVUNh=1_lL6ChQ3{yrC4KfoH4;R=hY?xN#3fSBLatAtw u#t*u3iuu_5N~+ia_W%DInE(H0V8o3<^5>ub{|~|-^$+;}|NkKW|33gzMrvIE literal 0 HcmV?d00001 diff --git a/src/qt/qt_iconindicators.cpp b/src/qt/qt_iconindicators.cpp index d5d22c78d..8440af7dc 100644 --- a/src/qt/qt_iconindicators.cpp +++ b/src/qt/qt_iconindicators.cpp @@ -12,6 +12,8 @@ getIndicatorIcon(IconIndicator indicator) return QIcon(":/settings/qt/icons/write_active.ico"); case Disabled: return QIcon(":/settings/qt/icons/disabled.ico"); + case WriteProtected: + return QIcon(":/settings/qt/icons/write_protected.ico"); default: return QIcon(); } @@ -26,11 +28,11 @@ getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, return iconPixmap; auto painter = QPainter(&iconPixmap); - auto indicatorPixmap = getIndicatorIcon(indicator == ReadWriteActive ? Active : indicator).pixmap(size); + auto indicatorPixmap = getIndicatorIcon((indicator == ReadWriteActive || indicator == WriteProtectedActive) ? Active : indicator).pixmap(size); painter.drawPixmap(0, 0, indicatorPixmap); - if (indicator == ReadWriteActive) { - auto writeIndicatorPixmap = getIndicatorIcon(WriteActive).pixmap(size); + if (indicator == ReadWriteActive || indicator == WriteProtectedActive) { + auto writeIndicatorPixmap = getIndicatorIcon(indicator == WriteProtectedActive ? WriteProtected : WriteActive).pixmap(size); painter.drawPixmap(0, 0, writeIndicatorPixmap); } painter.end(); diff --git a/src/qt/qt_iconindicators.hpp b/src/qt/qt_iconindicators.hpp index 12f82f259..d2232fc77 100644 --- a/src/qt/qt_iconindicators.hpp +++ b/src/qt/qt_iconindicators.hpp @@ -10,6 +10,8 @@ enum IconIndicator { WriteActive, ReadWriteActive, Disabled, + WriteProtected, + WriteProtectedActive, }; QPixmap getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator); diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index db32569f3..5a731c188 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -91,6 +91,8 @@ struct PixmapSetEmptyActive { QPixmap read_write_active; QPixmap empty_write_active; QPixmap empty_read_write_active; + QPixmap wp; + QPixmap wp_active; void load(const QIcon &icon); }; struct Pixmaps { @@ -168,6 +170,7 @@ struct StateEmptyActive { bool empty = false; bool active = false; bool write_active = false; + bool wp = false; void setActive(bool b) { @@ -193,6 +196,14 @@ struct StateEmptyActive { empty = b; refresh(); } + void setWriteProtected(bool b) + { + if (!label || b == wp) + return; + + wp = b; + refresh(); + } void refresh() { if (!label) @@ -203,7 +214,9 @@ struct StateEmptyActive { else label->setPixmap(write_active ? pixmaps->empty_write_active : (active ? pixmaps->empty_active : pixmaps->empty)); } else { - if (active && write_active) + if (wp) + label->setPixmap(active ? pixmaps->wp_active : pixmaps->wp); + else if (active && write_active) label->setPixmap(pixmaps->read_write_active); else label->setPixmap(write_active ? pixmaps->write_active : (active ? pixmaps->active : pixmaps->normal)); @@ -241,6 +254,8 @@ void PixmapSetEmptyActive::load(const QIcon &icon) { normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + wp = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, WriteProtected); + wp_active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, WriteProtectedActive); active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active); write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, WriteActive); read_write_active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, ReadWriteActive); @@ -454,16 +469,23 @@ MachineStatus::refreshEmptyIcons() if (!sbar_initialized) return; - for (size_t i = 0; i < FDD_NUM; ++i) + for (size_t i = 0; i < FDD_NUM; ++i) { d->fdd[i].setEmpty(machine_status.fdd[i].empty); + d->fdd[i].setWriteProtected(machine_status.fdd[i].write_prot); + } for (size_t i = 0; i < CDROM_NUM; ++i) d->cdrom[i].setEmpty(machine_status.cdrom[i].empty); - for (size_t i = 0; i < ZIP_NUM; i++) + for (size_t i = 0; i < ZIP_NUM; i++) { d->zip[i].setEmpty(machine_status.zip[i].empty); - for (size_t i = 0; i < MO_NUM; i++) + d->zip[i].setWriteProtected(machine_status.zip[i].write_prot); + } + for (size_t i = 0; i < MO_NUM; i++) { d->mo[i].setEmpty(machine_status.mo[i].empty); + d->mo[i].setWriteProtected(machine_status.mo[i].write_prot); + } d->cassette.setEmpty(machine_status.cassette.empty); + d->cassette.setWriteProtected(machine_status.cassette.write_prot); for (size_t i = 0; i < NET_CARD_MAX; i++) d->net[i].setEmpty(machine_status.net[i].empty); @@ -595,6 +617,7 @@ MachineStatus::refresh(QStatusBar *sbar) if (cassette_enable) { d->cassette.label = std::make_unique(); d->cassette.setEmpty(QString(cassette_fname).isEmpty()); + d->cassette.setWriteProtected(cassette_ui_writeprot); d->cassette.refresh(); connect((ClickableLabel *) d->cassette.label.get(), &ClickableLabel::clicked, [](QPoint pos) { MediaMenu::ptr->cassetteMenu->popup(pos - QPoint(0, MediaMenu::ptr->cassetteMenu->sizeHint().height())); @@ -635,6 +658,7 @@ MachineStatus::refresh(QStatusBar *sbar) } d->fdd[i].label = std::make_unique(); d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty()); + d->fdd[i].setWriteProtected(ui_writeprot[i]); d->fdd[i].setActive(false); d->fdd[i].setWriteActive(false); d->fdd[i].refresh(); @@ -669,6 +693,7 @@ MachineStatus::refresh(QStatusBar *sbar) iterateZIP([this, sbar](int i) { d->zip[i].label = std::make_unique(); d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty()); + d->zip[i].setWriteProtected(zip_drives[i].read_only); d->zip[i].setActive(false); d->zip[i].setWriteActive(false); d->zip[i].refresh(); @@ -686,6 +711,7 @@ MachineStatus::refresh(QStatusBar *sbar) iterateMO([this, sbar](int i) { d->mo[i].label = std::make_unique(); d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty()); + d->mo[i].setWriteProtected(mo_drives[i].read_only); d->mo[i].setActive(false); d->mo[i].setWriteActive(false); d->mo[i].refresh(); diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 11fac2a70..c9d658fb2 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -282,6 +282,7 @@ MediaMenu::cassetteMount(const QString &filename, bool wp) } ui_sb_update_icon_state(SB_CASSETTE, filename.isEmpty() ? 1 : 0); + ui_sb_update_icon_wp(SB_CASSETTE, cassette_ui_writeprot); mhm.addImageToHistory(0, ui::MediaType::Cassette, previous_image.filePath(), filename); cassetteUpdateMenu(); ui_sb_update_tip(SB_CASSETTE); @@ -446,6 +447,7 @@ MediaMenu::floppyMount(int i, const QString &filename, bool wp) fdd_load(i, filenameBytes.data()); } ui_sb_update_icon_state(SB_FLOPPY | i, filename.isEmpty() ? 1 : 0); + ui_sb_update_icon_wp(SB_FLOPPY | i, ui_writeprot[i]); mhm.addImageToHistory(i, ui::MediaType::Floppy, previous_image.filePath(), filename); floppyUpdateMenu(i); ui_sb_update_tip(SB_FLOPPY | i); @@ -822,6 +824,7 @@ MediaMenu::zipMount(int i, const QString &filename, bool wp) mhm.addImageToHistory(i, ui::MediaType::Zip, zip_drives[i].prev_image_path, zip_drives[i].image_path); ui_sb_update_icon_state(SB_ZIP | i, filename.isEmpty() ? 1 : 0); + ui_sb_update_icon_wp(SB_ZIP | i, wp); zipUpdateMenu(i); ui_sb_update_tip(SB_ZIP | i); @@ -858,6 +861,7 @@ MediaMenu::zipReloadPrev(int i) } else { ui_sb_update_icon_state(SB_ZIP | i, 0); } + ui_sb_update_icon_wp(SB_ZIP | i, zip_drives[i].read_only); zipUpdateMenu(i); ui_sb_update_tip(SB_ZIP | i); @@ -869,7 +873,7 @@ void MediaMenu::zipReload(int index, int slot) { const QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Zip); - zipMount(index, filename, false); + zipMount(index, filename, zip_drives[index].read_only); zipUpdateMenu(index); ui_sb_update_tip(SB_ZIP | index); } @@ -995,6 +999,7 @@ MediaMenu::moReloadPrev(int i) } else { ui_sb_update_icon_state(SB_MO | i, 0); } + ui_sb_update_icon_state(SB_MO | i, mo_drives[i].read_only); moUpdateMenu(i); ui_sb_update_tip(SB_MO | i); diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index 6e0b3cfbb..337b438f3 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -262,6 +262,34 @@ ui_sb_set_ready(int ready) } } +void +ui_sb_update_icon_wp(int tag, int state) +{ + const auto temp = static_cast(tag); + const int category = static_cast(temp & 0xfffffff0); + const int item = tag & 0xf; + + switch (category) { + default: + break; + case SB_CASSETTE: + machine_status.cassette.write_prot = state > 0 ? true : false; + break; + case SB_FLOPPY: + machine_status.fdd[item].write_prot = state > 0 ? true : false; + break; + case SB_ZIP: + machine_status.zip[item].write_prot = state > 0 ? true : false; + break; + case SB_MO: + machine_status.mo[item].write_prot = state > 0 ? true : false; + break; + } + + if (main_window != nullptr) + main_window->updateStatusEmptyIcons(); +} + void ui_sb_update_icon_state(int tag, int state) { diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 51518b8f6..9291892b5 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -28,6 +28,7 @@ qt/icons/zip.ico qt/icons/zip_disabled.ico qt/icons/active.ico + qt/icons/write_protected.ico qt/icons/write_active.ico qt/icons/disabled.ico qt/icons/86Box-gray.ico diff --git a/src/unix/unix.c b/src/unix/unix.c index f3580cd19..5a69424b4 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -948,6 +948,11 @@ void (*f_rl_callback_handler_remove)(void) = NULL; # define LIBEDIT_LIBRARY "libedit.so" #endif +void ui_sb_update_icon_wp(int tag, int state) +{ + /* No-op */ +} + uint32_t timer_onesec(uint32_t interval, UNUSED(void *param)) { From d0333f8350972c4fe15feeaf4214b21db61161ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Mon, 21 Jul 2025 05:40:05 +0200 Subject: [PATCH 5/5] Serial mouse: Fix a newly introduced bug. --- src/device/mouse_serial.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 341ddefe7..7310b0e6d 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -900,9 +900,11 @@ sermouse_init(const device_t *info) dev->status = 0x0f; dev->id_len = 1; dev->id[0] = 'M'; - if (info->local == 1) // Logitech Serial Mouse + 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: