diff --git a/apps/tzpu/tzpu.c b/apps/tzpu/tzpu.c index 46843a7..d8c8f97 100644 --- a/apps/tzpu/tzpu.c +++ b/apps/tzpu/tzpu.c @@ -123,6 +123,27 @@ void testSixtyBug(void) } } +void testVRAMLocation(void) +{ + printf("Requesting Z80 BUS and Mainboard access\n"); + if(reqMainboardBus(100) == 0) + { + setupSignalsForZ80Access(READ); + + for(uint32_t idx=0; idx < 0xFFFFFFFF; idx++) + { + uint8_t dataV = readZ80Memory(0xD000); + uint8_t dataA = readZ80Memory(0xD800); + printf("%02x %02x\r", dataV, dataA); + } + releaseZ80(); + } + else + { + printf("Failed to obtain the Z80 bus.\n"); + } +} + // Main entry and start point of a zOS/ZPUTA Application. Only 2 parameters are catered for and a 32bit return code, additional parameters can be added by changing the appcrt0.s // startup code to add them to the stack prior to app() call. @@ -148,6 +169,7 @@ uint32_t app(uint32_t param1, uint32_t param2) // _init_Teensyduino_internal_(); // setupZ80Pins(1, G->millis); // + testVRAMLocation(); testSixtyBug(); printf("Loading Monitor ROM\n"); diff --git a/common/tranzputer.c b/common/tranzputer.c index 3c88af8..e454d67 100644 --- a/common/tranzputer.c +++ b/common/tranzputer.c @@ -134,7 +134,6 @@ static void __attribute((naked, noinline)) irqPortE_dummy(void) asm volatile(" pop {r0-r1,pc} \n"); } -#if 0 static void __attribute((naked, noinline)) irqPortD_dummy(void) { // Save register we use. @@ -149,7 +148,6 @@ static void __attribute((naked, noinline)) irqPortD_dummy(void) asm volatile(" pop {r0-r1,pc} \n"); } -#endif #if 0 static void __attribute((naked, noinline)) irqPortC_dummy(void) { @@ -965,6 +963,28 @@ static void setupIRQ(void) return; } +// Method to remove the IRQ vectors and disable them. +// This method is called when the I/O processor goes 'silent', ie. not interacting with the host. +// +static void disableIRQ(void) +{ + __disable_irq(); + + // Vectors to dummy routines. + _VectorsRam[IRQ_PORTD + 16] = irqPortD_dummy; + _VectorsRam[IRQ_PORTE + 16] = irqPortE_dummy; + + // Remove the interrupts. + removeIRQ(TZ_SVCREQ); + removeIRQ(TZ_SYSREQ); + removeIRQ(Z80_IORQ); + removeIRQ(Z80_RESET); + + __enable_irq(); + return; +} + + // Method to restore the interrupt vector when the pin mode is changed and restored to default input mode. // static void restoreIRQ(void) @@ -1136,6 +1156,7 @@ void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick) z80Control.runCtrlLatch = readCtrlLatch(); z80Control.ctrlMode = Z80_RUN; z80Control.busDir = TRISTATE; + z80Control.hostType = MZ80A; z80Control.machineMode = MZ80A; // Final part of first call initialisation, now that the pins are configured, setup the interrupts. @@ -1163,13 +1184,13 @@ void setupZ80Pins(uint8_t initTeensy, volatile uint32_t *millisecondTick) // Debug to quickly find out addresses of GPIO pins. #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) - printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSRQ", digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg + 64 ); - printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WAIT", digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg, digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg + 64 ); - printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSACK", digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg + 64 ); - printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_IORQ", digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg + 64 ); - printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_MREQ", digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg + 64 ); - printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_RD", digital_pin_to_info_PGM[(Z80_RD_PIN)].reg, digital_pin_to_info_PGM[(Z80_RD_PIN)].reg + 64 ); - printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WR", digital_pin_to_info_PGM[(Z80_WR_PIN)].reg, digital_pin_to_info_PGM[(Z80_WR_PIN)].reg + 64 ); + //printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSRQ", digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSRQ_PIN)].reg + 64 ); + //printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WAIT", digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg, digital_pin_to_info_PGM[(Z80_WAIT_PIN)].reg + 64 ); + //printf("%s, Set=%08lx, Clear=%08lx\n", "CTL_BUSACK", digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg, digital_pin_to_info_PGM[(CTL_BUSACK_PIN)].reg + 64 ); + //printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_IORQ", digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_IORQ_PIN)].reg + 64 ); + //printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_MREQ", digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg, digital_pin_to_info_PGM[(Z80_MREQ_PIN)].reg + 64 ); + //printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_RD", digital_pin_to_info_PGM[(Z80_RD_PIN)].reg, digital_pin_to_info_PGM[(Z80_RD_PIN)].reg + 64 ); + //printf("%s, Set=%08lx, Clear=%08lx\n", "Z80_WR", digital_pin_to_info_PGM[(Z80_WR_PIN)].reg, digital_pin_to_info_PGM[(Z80_WR_PIN)].reg + 64 ); return; } @@ -1398,6 +1419,23 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data) // Locals. uint32_t startTime = *ms; + // Video RAM has a blanking circuit which causes the Z80 to enter a WAIT state. The K64F can only read the WAIT state and sometimes will miss it + // so wait for the start of a blanking period and write. + // + //if(z80Control.ctrlMode == MAINBOARD_ACCESS && addr >= 0xD000 && addr < 0xE000) + //{ + // uint8_t blnkDet, blnkDetLast; + // blnkDet = 0x80; + // setZ80Direction(READ); + // do { + // blnkDetLast = blnkDet; + // blnkDet = readZ80Memory(0xE008) & 0x80; + // } while(!(blnkDet == 0x80 && blnkDetLast == 0x00)); + // for(volatile uint32_t pulseWidth=0; pulseWidth < 10; pulseWidth++); + // setZ80Direction(WRITE); + // startTime = *ms; + //} + // Set the data and address on the bus. // setZ80Addr(addr); @@ -1424,7 +1462,7 @@ uint8_t writeZ80Memory(uint16_t addr, uint8_t data) #if TZBOARD == 100 || TZBOARD == 110 for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++); #elif TZBOARD == 200 || TZBOARD == 210 - for(volatile uint32_t pulseWidth=0; pulseWidth < 5; pulseWidth++); + for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++); #endif // Another wait loop check as the Z80 can assert wait at the time of Write or anytime before it is deasserted. @@ -1459,20 +1497,36 @@ uint8_t readZ80Memory(uint16_t addr) uint32_t startTime = *ms; uint8_t data; + // Video RAM has a blanking circuit which causes the Z80 to enter a WAIT state. The K64F can only read the WAIT state and sometimes will miss it + // so wait for the start of a blanking period and read. + // + if(z80Control.ctrlMode == MAINBOARD_ACCESS && addr >= 0xD000 && addr < 0xE000) + { + uint8_t blnkDet, blnkDetLast; + blnkDet = 0x80; + do { + blnkDetLast = blnkDet; + blnkDet = readZ80Memory(0xE008) & 0x80; + } while(!(blnkDet == 0x80 && blnkDetLast == 0x00)); + for(volatile uint32_t pulseWidth=0; pulseWidth < 10; pulseWidth++); + startTime = *ms; + } + // Set the address on the bus and assert MREQ and RD. // setZ80Addr(addr); + + // Setup time before applying control signals. + for(volatile uint32_t pulseWidth = 0; pulseWidth < 3; pulseWidth++); pinLow(Z80_MREQ); pinLow(Z80_RD); + for(volatile uint32_t pulseWidth = 0; pulseWidth < 3; pulseWidth++); // Different logic according to what is being accessed. The mainboard needs to uphold timing and WAIT signals whereas the Tranzputer logic has no wait // signals and faster memory. // if(z80Control.ctrlMode == MAINBOARD_ACCESS) { - // A wait loop check as the Z80 can assert wait during the Read operation to request more time. Set a timeout in case of hardware lockup. - while((*ms - startTime) < 100 && pinGet(Z80_WAIT) == 0); - // On a Teensy3.5 K64F running at 120MHz this delay gives a pulsewidth of 760nS. This gives time for the addressed device to present the data // on the data bus. #if TZBOARD == 100 || TZBOARD == 110 @@ -1481,6 +1535,9 @@ uint8_t readZ80Memory(uint16_t addr) #elif TZBOARD == 200 || TZBOARD == 210 for(volatile uint32_t pulseWidth=0; pulseWidth < 4; pulseWidth++); #endif + + // A wait loop check as the Z80 can assert wait during the Read operation to request more time. Set a timeout in case of hardware lockup. + while((*ms - startTime) < 100 && pinGet(Z80_WAIT) == 0); } else { // On the tranZPUter v1.1, because of reorganisation of the signals, the time to process is less and so the pulse width under v1.0 is insufficient. @@ -1712,7 +1769,7 @@ void setCtrlLatch(uint8_t latchVal) { // Gain control of the bus then set the latch value. // - if(reqTranZPUterBus(100) == 0) + if(reqTranZPUterBus(500) == 0) { // Setup the pins to perform a write operation. // @@ -1749,7 +1806,7 @@ uint32_t setZ80CPUFrequency(float frequency, uint8_t action) { // Gain control of the bus to change the CPU frequency latch. // - if(reqTranZPUterBus(100) == 0) + if(reqTranZPUterBus(500) == 0) { // Setup the pins to perform a write operation. // @@ -1779,7 +1836,7 @@ uint8_t copyFromZ80(uint8_t *dst, uint32_t src, uint32_t size, uint8_t mainBoard // Request the correct bus. // - if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) ) + if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) ) { // Setup the pins to perform a read operation (after setting the latch to starting value). // @@ -1838,7 +1895,7 @@ uint8_t copyToZ80(uint32_t dst, uint8_t *src, uint32_t size, uint8_t mainBoard) // Request the correct bus. // - if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) ) + if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) ) { // Setup the pins to perform a write operation. // @@ -1886,7 +1943,7 @@ void fillZ80Memory(uint32_t addr, uint32_t size, uint8_t data, uint8_t mainBoard // Locals. uint8_t upperAddrBits = 0; - if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) ) + if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) ) { // Setup the pins to perform a read operation (after setting the latch to starting value). // @@ -1929,7 +1986,7 @@ void captureVideoFrame(enum VIDEO_FRAMES frame, uint8_t noAttributeFrame) { // Locals. - if(reqMainboardBus(100) == 0) + if(reqMainboardBus(500) == 0) { // Setup the pins to perform a read operation (after setting the latch to starting value). // @@ -1976,7 +2033,7 @@ void refreshVideoFrame(enum VIDEO_FRAMES frame, uint8_t scrolHome, uint8_t noAtt { // Locals. - if(reqMainboardBus(100) == 0) + if(reqMainboardBus(500) == 0) { // Setup the pins to perform a write operation. // @@ -2163,10 +2220,10 @@ FRESULT loadZ80Memory(const char *src, uint32_t fileOffset, uint32_t addr, uint3 // Request the board according to the mainboard flag, mainboard = 1 then the mainboard is controlled otherwise the tranZPUter board. if(mainBoard == 0) { - reqTranZPUterBus(100); + reqTranZPUterBus(500); } else { - reqMainboardBus(100); + reqMainboardBus(500); } // If successful, setup the control pins for upload mode. @@ -2350,7 +2407,7 @@ FRESULT saveZ80Memory(const char *dst, uint32_t addr, uint32_t size, t_svcDirEnt if(!fr0) { - if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) ) + if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) ) { // Setup the pins to perform a read operation (after setting the latch to starting value). // @@ -2444,7 +2501,7 @@ int memoryDumpZ80(uint32_t memaddr, uint32_t memsize, uint32_t dispaddr, uint8_t // Request the correct bus. // - if( (mainBoard == 0 && reqTranZPUterBus(100) == 0) || (mainBoard != 0 && reqMainboardBus(100) == 0) ) + if( (mainBoard == 0 && reqTranZPUterBus(500) == 0) || (mainBoard != 0 && reqMainboardBus(500) == 0) ) { // Setup the pins to perform a read operation (after setting the latch to starting value). // @@ -2631,6 +2688,31 @@ void convertSharpFilenameToAscii(char *dst, char *src, uint8_t size) // // ////////////////////////////////////////////////////////////// +// Method to load a BIOS into the tranZPUter and configure for a particular host type. +// +uint8_t loadBIOS(const char *biosFileName, uint8_t machineMode, uint32_t loadAddr) +{ + // Locals. + uint8_t result = FR_OK; + + // Load up the given BIOS into tranZPUter memory. + if((result=loadZ80Memory(biosFileName, 0, loadAddr, 0, 0, 0, 1)) != FR_OK) + { + printf("Error: Failed to load %s into tranZPUter memory.\n", biosFileName); + } else + { + // Change frequency to default. + setZ80CPUFrequency(0, 4); + + // Set the machine mode according to BIOS loaded. + z80Control.machineMode = machineMode; + + // setup the IRQ's according to this machine. + setupIRQ(); + } + return(result); +} + // Method to load the default ROMS into the tranZPUter RAM ready for start. // If the autoboot flag is set, perform autoboot by wiping the STACK area // of the SA1510 - this has the effect of JP 00000H. @@ -2644,10 +2726,21 @@ void loadTranZPUterDefaultROMS(void) fillZ80Memory(0x000000, 0x10000, 0x00, 0); // TZFS and Sharp MZ80A mode. fillZ80Memory(0x040000, 0x20000, 0x00, 0); // CPM Mode. - // Now load the necessary images into memory. - if((result=loadZ80Memory((const char *)MZ_ROM_SA1510_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK) + // Now load the default BIOS into memory for the host type. + switch(z80Control.hostType) { - printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_SA1510_40C); + case MZ700: + result = loadBIOS(MZ_ROM_1Z_013A_40C, MZ700, MZ_MROM_ADDR); + break; + + case MZ80B: + result = loadBIOS(MZ_ROM_MZ80B_IPL, MZ700, MZ_MROM_ADDR); + break; + + case MZ80A: + default: + result = loadBIOS(MZ_ROM_SA1510_40C, MZ80A, MZ_MROM_ADDR); + break; } if(!result && (result=loadZ80Memory((const char *)MZ_ROM_TZFS, 0, MZ_UROM_ADDR, 0x1800, 0, 0, 1) != FR_OK)) { @@ -2696,7 +2789,7 @@ uint8_t setZ80SvcStatus(uint8_t status) // Request the tranZPUter bus. // - if(reqTranZPUterBus(100) == 0) + if(reqTranZPUterBus(500) == 0) { // Setup the pins to perform a write operation. // @@ -4188,41 +4281,45 @@ void processServiceRequest(void) status=svcCacheDir((const char *)svcControl.directory, svcControl.fileType, 0); break; - // Load the 40 column version of the SA1510 bios into memory. + // Load the 40 column version of the default host bios into memory. case TZSVC_CMD_LOAD40BIOS: - if((status=loadZ80Memory((const char *)MZ_ROM_SA1510_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK) + switch(z80Control.hostType) { - printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_SA1510_40C); + case MZ700: + loadBIOS(MZ_ROM_1Z_013A_40C, MZ700, MZ_MROM_ADDR); + break; + + case MZ80B: + loadBIOS(MZ_ROM_MZ80B_IPL, MZ700, MZ_MROM_ADDR); + break; + + case MZ80A: + default: + loadBIOS(MZ_ROM_SA1510_40C, MZ80A, MZ_MROM_ADDR); + break; } - - // Change frequency to default. - setZ80CPUFrequency(MZ_80A_CPU_FREQ, 2); - - // Set the machine mode according to BIOS loaded. - z80Control.machineMode = MZ80A; - - // setup the IRQ's according to this machine. - setupIRQ(); break; - // Load the 80 column version of the SA1510 bios into memory. + // Load the 80 column version of the default host bios into memory. case TZSVC_CMD_LOAD80BIOS: - if((status=loadZ80Memory((const char *)MZ_ROM_SA1510_80C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK) + switch(z80Control.hostType) { - printf("Error: Failed to load %s into tranZPUter memory.\n", MZ_ROM_SA1510_80C); - } - - // Change frequency to default. - setZ80CPUFrequency(MZ_80A_CPU_FREQ, 2); - - // Set the machine mode according to BIOS loaded. - z80Control.machineMode = MZ80A; + case MZ700: + loadBIOS(MZ_ROM_1Z_013A_80C, MZ700, MZ_MROM_ADDR); + break; - // setup the IRQ's according to this machine. - setupIRQ(); + case MZ80B: + loadBIOS(MZ_ROM_MZ80B_IPL, MZ700, MZ_MROM_ADDR); + break; + + case MZ80A: + default: + loadBIOS(MZ_ROM_SA1510_80C, MZ80A, MZ_MROM_ADDR); + break; + } break; - // Load the 40 column MZ700 1Z-013A bios into memory. + // Load the 40 column MZ700 1Z-013A bios into memory for compatibility switch. case TZSVC_CMD_LOAD700BIOS40: #if TZBOARD == 100 || TZBOARD == 110 if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_KM_40C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK) @@ -4243,7 +4340,7 @@ void processServiceRequest(void) setupIRQ(); break; - // Load the 80 column MZ700 1Z-013A bios into memory. + // Load the 80 column MZ700 1Z-013A bios into memory for compatibility switch. case TZSVC_CMD_LOAD700BIOS80: #if TZBOARD == 100 || TZBOARD == 110 if((status=loadZ80Memory((const char *)MZ_ROM_1Z_013A_KM_80C, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK) @@ -4264,7 +4361,7 @@ void processServiceRequest(void) setupIRQ(); break; - // Load the MZ-80B IPL ROM into memory. + // Load the MZ-80B IPL ROM into memory for compatibility switch. case TZSVC_CMD_LOAD80BIPL: if((status=loadZ80Memory((const char *)MZ_ROM_MZ80B_IPL, 0, MZ_MROM_ADDR, 0, 0, 0, 1)) != FR_OK) { @@ -4327,6 +4424,27 @@ void processServiceRequest(void) svcControl.cpuFreq = (uint16_t)(actualFreq / 1000); break; + // Command to exit from TZFS and return machine to original mode. + case TZSVC_CMD_EXIT: + // Disable secondary frequency. + setZ80CPUFrequency(0, 4); + + // Set the memory model to ORIGinal. + setCtrlLatch(TZMM_ORIG); + + // Clear the stack and monitor variable area as DRAM wont have been refreshed so will contain garbage. + fillZ80Memory(MZ_MROM_STACK_ADDR, MZ_MROM_STACK_SIZE, 0x00, 1); + + // Set to refresh mode just in case the I/O processor performs any future action in silent mode! + z80Control.disableRefresh = 0; + + // Now reset the machine so everything starts as power on. + resetZ80(); + + // Disable the interrupts so no further service processing. + disableIRQ(); + break; + default: printf("WARNING: Unrecognised command:%02x\n", svcControl.cmd); break; @@ -4362,6 +4480,45 @@ uint8_t testTZFSAutoBoot(void) return(result); } +// Method to identify the type of host the tranZPUter SW is running on. Originally it was only the MZ80A but the scope has expanded +// to the MZ-700 and MZ-80B and potentially a plethora of other machines in the future. +// +void setHost(void) +{ + // Locals. + uint8_t buf[4]; + + // Copy the ID value from the host monitor so that we can identify the host type. + // + copyFromZ80(buf, HOST_MON_TEST_VECTOR, 1, 1); + + // Setup the control variable to indicate type of host. This will affect processing of interrupts, BIOS loads etc. + // + switch(buf[0]) + { + case MZ700_MONITOR_ID: + z80Control.hostType = MZ700; + z80Control.machineMode = MZ700; + printf("Host Type: MZ-700\n"); + break; + + case MZ80B_MONITOR_ID: + z80Control.hostType = MZ80B; + z80Control.machineMode = MZ80B; + printf("Host Type: MZ-80B\n"); + break; + + case MZ80A_MONITOR_ID: + default: + z80Control.hostType = MZ80A; + z80Control.machineMode = MZ80A; + printf("Host Type: MZ-80A\n"); + break; + } + + return; +} + // Method to configure the hardware and events to operate the tranZPUter SW upgrade. // void setupTranZPUter(void) @@ -4369,6 +4526,12 @@ void setupTranZPUter(void) // Setup the pins to default mode and configure IRQ's. setupZ80Pins(0, &systick_millis_count); + // Check to see which monitor is installed to determine the host type. + setHost(); + + // Reset the interrupts so they take into account the current host rather than the default. + setupIRQ(); + // Check to see if autoboot is needed. osControl.tzAutoBoot = testTZFSAutoBoot(); diff --git a/include/tranzputer.h b/include/tranzputer.h index c75efbd..f0322b4 100755 --- a/include/tranzputer.h +++ b/include/tranzputer.h @@ -36,7 +36,7 @@ // Configurable constants. // -//#define DECODE_Z80_IO 3 // Flag to enable code, via interrupt, to capture Z80 actions on I/O ports an Memory mapped I/O. +//#define DECODE_Z80_IO 3 // Flag to enable code, via interrupt, to capture Z80 actions on I/O ports an Memory mapped I/O. // 0 = No code other than direct service request interrupts. // 1 = Decode Z80 I/O address operations. // 2 = Decode Z80 I/O operations with data. @@ -44,6 +44,7 @@ #define REFRESH_BYTE_COUNT 8 // This constant controls the number of bytes read/written to the z80 bus before a refresh cycle is needed. #define RFSH_BYTE_CNT 256 // Number of bytes we can write before needing a full refresh for the DRAM. #define TZBOARD 210 // tranZPUter SW Hardware versions - v1.0 = 110, v1.1 = 110, v2.0 = 200 and v2.1 = 210 +#define HOST_MON_TEST_VECTOR 0x4 // Address in the host monitor to test to identify host type. // tranZPUter Memory Modes - select one of the 32 possible memory models using these constants. // @@ -156,6 +157,7 @@ #define TZSVC_CMD_CPU_BASEFREQ 0x40 // Service command to switch to the mainboard frequency. #define TZSVC_CMD_CPU_ALTFREQ 0x41 // Service command to switch to the alternate frequency provided by the K64F. #define TZSVC_CMD_CPU_CHGFREQ 0x42 // Service command to set the alternate frequency in hertz. +#define TZSVC_CMD_EXIT 0x7F // Service command to terminate TZFS and restart the machine in original mode. #define TZSVC_DEFAULT_MZF_DIR "MZF" // Default directory where MZF files are stored. #define TZSVC_DEFAULT_CAS_DIR "CAS" // Default directory where BASIC CASsette files are stored. #define TZSVC_DEFAULT_BAS_DIR "BAS" // Default directory where BASIC text files are stored. @@ -411,9 +413,17 @@ enum VIDEO_FRAMES { WORKING = 1 }; -// Possible machines the tranZPUter can emulate. +// Values in the host monitor ROM to identify a machine type. // -enum MACHINE_MODE { +enum MACHINE_MONITOR_ID { + MZ80A_MONITOR_ID = 0xa8, + MZ700_MONITOR_ID = 0xe6, + MZ80B_MONITOR_ID = 0x03 +}; + +// Possible machines the tranZPUter can be hosted on and can emulate. +// +enum MACHINE_TYPES { MZ80A = 0, MZ700 = 1, MZ80B = 2 @@ -519,8 +529,8 @@ typedef struct { enum CTRL_MODE ctrlMode; // Mode of control, ie normal Z80 Running, controlling mainboard, controlling tranZPUter. enum BUS_DIRECTION busDir; // Direction the bus has been configured for. - - enum MACHINE_MODE machineMode; // Machine compatibility, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B + enum MACHINE_TYPES hostType; // The underlying host machine, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B + enum MACHINE_TYPES machineMode; // Machine compatibility, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B t_mz700 mz700; // MZ700 emulation control to detect IO commands and adjust the memory map accordingly. t_mz80b mz80b; // MZ-80B emulation control to detect IO commands and adjust the memory map and I/O forwarding accordingly. @@ -675,9 +685,11 @@ uint8_t svcReadCPMDrive(void); uint8_t svcWriteCPMDrive(void); uint32_t getServiceAddr(void); void processServiceRequest(void); +uint8_t loadBIOS(const char *biosFileName, uint8_t machineMode, uint32_t loadAddr); void loadTranZPUterDefaultROMS(void); void tranZPUterControl(void); uint8_t testTZFSAutoBoot(void); +void setHost(void); void setupTranZPUter(void); #if defined __APP__ diff --git a/libraries/lib/libimath2-k64f.a b/libraries/lib/libimath2-k64f.a index 8372f73..c9cec1c 100644 Binary files a/libraries/lib/libimath2-k64f.a and b/libraries/lib/libimath2-k64f.a differ diff --git a/libraries/lib/libumansi-k64f.a b/libraries/lib/libumansi-k64f.a index bbc2b82..8095e6b 100644 Binary files a/libraries/lib/libumansi-k64f.a and b/libraries/lib/libumansi-k64f.a differ diff --git a/libraries/lib/libummath-k64f.a b/libraries/lib/libummath-k64f.a index 4e5fe1a..2136c72 100644 Binary files a/libraries/lib/libummath-k64f.a and b/libraries/lib/libummath-k64f.a differ diff --git a/libraries/lib/libummathf-k64f.a b/libraries/lib/libummathf-k64f.a index 8de27e7..ffb2bf8 100644 Binary files a/libraries/lib/libummathf-k64f.a and b/libraries/lib/libummathf-k64f.a differ diff --git a/libraries/lib/libummisc-k64f.a b/libraries/lib/libummisc-k64f.a index f33dc6b..c835351 100644 Binary files a/libraries/lib/libummisc-k64f.a and b/libraries/lib/libummisc-k64f.a differ diff --git a/libraries/lib/libumstdio-k64f.a b/libraries/lib/libumstdio-k64f.a index 59578eb..e70ae9f 100644 Binary files a/libraries/lib/libumstdio-k64f.a and b/libraries/lib/libumstdio-k64f.a differ