diff --git a/projects/tzpuPico/src/Z80CPU.c b/projects/tzpuPico/src/Z80CPU.c index 311cc0a..1ac9a01 100644 --- a/projects/tzpuPico/src/Z80CPU.c +++ b/projects/tzpuPico/src/Z80CPU.c @@ -2937,8 +2937,7 @@ uint8_t __func_in_RAM(Z80CPU_fetchOpcode)(void *context, uint16_t address) // DRAM refresh: when fetching opcodes from virtual memory, the physical M1 cycle // (which includes a RFSH bus cycle) is not generated. Physical DRAM on the host - // motherboard will decay without a refresh. Trigger a full M1 cycle but ignore - // the read opcode. + // motherboard will decay without a refresh. if(cpu->refreshEnable) { Z80CPU_refreshDRAM(context, true, address, data); @@ -3578,16 +3577,6 @@ uint8_t __func_in_RAM(Z80CPU_refreshDRAM)(void *context, bool read, uint16_t add // Wait until the previous cycle completes before commencing new cycle. WAIT_IRQ_SET(pio_1, smCycle); -// // No waiting, we just push 8 instructions which form T1/T2 and exit. -// PUSH_INSTR32(pio_1, -// smCycle, -// 0xfc0e, // set pins, 14 side 3 Set /M1 low -// 0x2013); // T1 wait 0 gpio, 35 -// PUSH_INSTR32(pio_1, -// smCycle, -// 0xf80a, // set pins, 10 side 2 Set /M1 low, /MREQ low, /RD low -// (0x0000 + offsetCycle + 6)); // jmp offset+6, wait state loop. - // Push initial instructions to setup pin inactive state then execute the Refresh T3/T4 cycles. PUSH_INSTR32(pio_1, smCycle, diff --git a/projects/tzpuPico/src/drivers/Sharp/MZ80A.c b/projects/tzpuPico/src/drivers/Sharp/MZ80A.c index b758313..9afda42 100644 --- a/projects/tzpuPico/src/drivers/Sharp/MZ80A.c +++ b/projects/tzpuPico/src/drivers/Sharp/MZ80A.c @@ -925,8 +925,7 @@ uint8_t MZ80A_Init(t_Z80CPU *cpu, t_FlashAppConfigHeader *appConfig, t_drvConfig // When the driver is PHYSICAL, interface ROM loading (MZ80A_readROMData) may have // changed F000-FFFF from PHYSICAL to ROM type. Restore to PHYSICAL so the hardware - // ROM is used — virtual ROM + physical FDC hardware doesn't work because the virtual - // WD1773 DRQ can't toggle the real hardware's A10 line. + // ROM is used — the physical FDC hardware handles DRQ/A10 directly on the bus. if (config->isPhysical) { for (int idx = 0xF000 / MEMORY_BLOCK_SIZE; idx < 0x10000 / MEMORY_BLOCK_SIZE; idx++) @@ -934,6 +933,31 @@ uint8_t MZ80A_Init(t_Z80CPU *cpu, t_FlashAppConfigHeader *appConfig, t_drvConfig cpu->_membankPtr[idx] = (MEMBANK_TYPE_PHYSICAL << 24) | (MZ80A_MEMBANK_0 << 16) | (idx * MEMORY_BLOCK_SIZE); } } + else + { + // VIRTUAL driver + PHYSICAL MZ80AFI interface: the floppy ROM is in virtual RAM + // but the FDC is physical hardware. Install a software A10 toggle handler that + // reads DRQ from the physical WD1773 to bridge the gap. + for (int ifIdx2 = 0; ifIdx2 < config->ifCount; ifIdx2++) + { + if (strncasecmp(config->ifConfig[ifIdx2].name, "MZ80AFI", 7) == 0 && + config->ifConfig[ifIdx2].isPhysical) + { + MEMIO_SET(cpu, 0xF3FE, (t_MemoryFunc) MZ80AFI_IO_A10Toggle); + MEMIO_SET(cpu, 0xF3FF, (t_MemoryFunc) MZ80AFI_IO_A10Toggle); + break; + } + } + } + + // When any interface uses physical hardware, RFS bank switching will change + // blocks from PHYSICAL to RAM type. The Z80 then fetches from virtual RAM + // without generating physical M1/RFSH cycles, causing host DRAM to decay. + // Force refreshEnable so Z80CPU_refreshDRAM is called during virtual fetches. + if (config->isPhysical) + { + cpu->refreshEnable = true; + } // Install MZ-80A MEMSW/MEMSWR handlers, overriding any installed by RFS_Init. // The MZ-80A has hardware MEMSW support — in PHYSICAL mode the handler must also @@ -943,7 +967,7 @@ uint8_t MZ80A_Init(t_Z80CPU *cpu, t_FlashAppConfigHeader *appConfig, t_drvConfig mz80aMemSwitch = false; MEMIO_SET(cpu, MEMSW, (t_MemoryFunc) MZ80A_IO_MEMSW); MEMIO_SET(cpu, MEMSWR, (t_MemoryFunc) MZ80A_IO_MEMSWR); -/* + // Debug: dump memory attributes for key blocks to verify tCycSync and waitStates. debugf("MZ80A_Init: Memory attributes (bank 0):\r\n"); for (int idx = 0; idx < MEMORY_PAGE_BLOCKS; idx++) @@ -958,7 +982,7 @@ uint8_t MZ80A_Init(t_Z80CPU *cpu, t_FlashAppConfigHeader *appConfig, t_drvConfig idx, idx * MEMORY_BLOCK_SIZE, type, ws, ts, mbp); } } -*/ + } } diff --git a/projects/tzpuPico/src/drivers/Sharp/MZ80AFI.c b/projects/tzpuPico/src/drivers/Sharp/MZ80AFI.c index 8ae3fb9..cbe0a05 100644 --- a/projects/tzpuPico/src/drivers/Sharp/MZ80AFI.c +++ b/projects/tzpuPico/src/drivers/Sharp/MZ80AFI.c @@ -43,6 +43,7 @@ #include "drivers/Sharp/MZ80AFI.h" t_MZ80AFI *mz80afiCtrl; // Control structure for the MZ80AFI Floppy Disk Interface. +static bool mz80afiIsPhysical = false; // True when MZ80AFI interface is physical (hardware FDC). // ----------------------------------------------------------------------------------------------- // Interface: Sharp MZ-80A Floppy Disk Interface Board (MZ80AFI). @@ -57,7 +58,10 @@ uint8_t MZ80AFI_Init(t_Z80CPU *cpu, t_drvIFConfig *config) // Locals. uint8_t result = 0; - // Interface logic only for virtual device. Physical device doesnt need configuration. + // Physical device doesn't need virtual FDC setup. The A10 toggle handler for + // VIRTUAL driver + PHYSICAL interface is installed by MZ80A_Init, which has + // visibility of both the driver and interface physical flags. + mz80afiIsPhysical = config->isPhysical; if (config->isPhysical) return (0); @@ -183,11 +187,14 @@ uint8_t MZ80AFI_TaskProcessor(t_Z80CPU *cpu, enum Z80CPU_TASK_NAME task, char *p switch (task) { case FLOPPY_DISK_CHANGE: - int diskNo = atoi(strtok(param, ",")); - char *fileName = strtok(NULL, ","); - if (fileName != NULL) + if (mz80afiCtrl) { - wd1773_changeDisk(&mz80afiCtrl->fdc, fileName, diskNo); + int diskNo = atoi(strtok(param, ",")); + char *fileName = strtok(NULL, ","); + if (fileName != NULL) + { + wd1773_changeDisk(&mz80afiCtrl->fdc, fileName, diskNo); + } } break; @@ -212,12 +219,20 @@ uint8_t __func_in_RAM(MZ80AFI_IO_A10Toggle)(t_Z80CPU *cpu, bool read, uint16_t a return data; // When DRQ is active, force A10 high — F3FE reads as F7FE, F3FF reads as F7FF. - uint16_t effectiveAddr = addr; - if (mz80afiCtrl != NULL && mz80afiCtrl->fdc.drq) + bool drq = false; + if (mz80afiIsPhysical) { - effectiveAddr = addr | 0x0400; + // Physical FDC: read WD1773 status register via physical bus. + // MZ-80A inverts the data bus for the FDC, so DRQ (bit 1) is 0 when active. + uint8_t status = Z80CPU_readPhysicalIO(cpu, 0xD8); + drq = !(status & 0x02); + } + else if (mz80afiCtrl != NULL) + { + drq = mz80afiCtrl->fdc.drq; } + uint16_t effectiveAddr = drq ? (addr | 0x0400) : addr; return cpu->_z80PSRAM->RAM[effectiveAddr]; } diff --git a/projects/tzpuPico/src/model/BaseZ80/version.txt b/projects/tzpuPico/src/model/BaseZ80/version.txt index bb62338..0dc433a 100644 --- a/projects/tzpuPico/src/model/BaseZ80/version.txt +++ b/projects/tzpuPico/src/model/BaseZ80/version.txt @@ -1 +1 @@ -2.222 +2.242 diff --git a/projects/tzpuPico/version.txt b/projects/tzpuPico/version.txt index aacb309..a964a46 100644 --- a/projects/tzpuPico/version.txt +++ b/projects/tzpuPico/version.txt @@ -1 +1 @@ -2.209 +2.226