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 zcmeI2J#ND=422mqC{T3CkRe+=cI*wBspsfa6v!cJpi9Rdqf_Ues#kCxO$ZSL(vg** zKfohEOQJ=|{wz{L5Rru}WwjENojfl^9zqbJ*La9F&*y@=QCHeSVlC>^s(Ys;4Kg?lkJc=!~Q%HaW zNPq-#0{uO51#)9Vcm{?F>O=;2$>C=xYr$|F4WN}d_E&2RZ|NNQAOAe!n*J#jAl=WuWRI3J?Kyi23+;n;W-s7m$ z)vG!Kbp{@92AU&fGz-nfM8AyQP2}O!H~Qsj{I`7H(eGaG-;jYx=8HRsx#lin9&2MA z{dtV(aaihkY?zCBug*Z7fg3Y0a(gek;}?z0UopR3nH%ET`h0)dFWbM6pZ>I5w%6Mq z8^H1LtB)Uh2KIOm`Exvz+^fWMO1zS{F?de-`F>4R^{!oxtLLBL`*t~7uj&lc8F&O4 zxH5~zgGN;b)y;B`Xx`&E=FgGOkF`H&_&@EGpBMW-Gv2V}^^o_&+r@o0e(H>E|33TS zmiuh<6}bPEN#o7xLxXcj@|GIsf(5J6T=*SbhT~Ez)YW;zKewHzx}V3$nDd zB+JXova+%wDJ5B3Ta%5A4cXe-lI`tn+1c5VoU`oi?#llDz8oAJ$l>9ksHz+t9m()VwI~dZ z_;5l7A&9{d4JKqL2t^!`goF%*A@W6SSu$&d!4bh^C=8AWE+IoY*?==!jUThr-~XbGo1&3d79I^tCcID8o}z{9j5bQ~$bdvMQtf-Vom~ Ss)xNNFD~SFxL+`wzxD&9mw}%E From 6b2e58d3b4cdfbba302b2aee432478b4dc499250 Mon Sep 17 00:00:00 2001 From: Cacodemon345 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 zcmeHNy>1jS5T1w#gi??qMY>!`$r~gU&p{RO7I!BaN*;rXn(l5ZL<6r7iGmK1CotbP z_T2g$FX#2{Ns;1_M&qCLH{*$KW^6^|L{8=WTp$H8mF zirk)wEEc~18SDPw+t*lwCJ_8Mgxp|VqvnAldB6eJc&rL1&N*2wJ$sxo46Gr^YUO#o zh6GM2Mp&;HisW3k-FmDt3q*BOA8qJm>1r%n1Wvm2~z5NoYx#qWdt zuIuXmt{FRsX;gd9&%o{tQ3rWStrY{By<_BdiTdjr=j>{qIral{oWFC<-Gf<&ExsO0?I?*_U3g`@XC9P3>nX9M?|@?7r@slEprtr*z8z`MjV{BH4&3`5NMpT9lx M`@2`p{k?MTA5%tZT>t<8 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: