From f72a4e6be6203febf82549460dd86e6a9484fcfb Mon Sep 17 00:00:00 2001 From: Philip Smart Date: Sun, 7 Mar 2021 23:31:30 +0000 Subject: [PATCH] Updates for the tranZPUter SW v2.2 on the MZ800 --- CPLD/SW/build/tranZPUterSW.qsf | 31 +- CPLD/SW/build/tranZPUterSW_constraints.sdc | 90 +- CPLD/SW/tranZPUterSW.vhd | 959 +++--- CPLD/SW/tranZPUterSW_Toplevel.vhd | 153 +- CPLD/SW/tranZPUterSW_pkg.vhd | 52 +- CPLD/SW700/v1.2/tranZPUterSW700.vhd | 133 +- CPLD/SW700/v1.2/tranZPUterSW700_Toplevel.vhd | 2 +- .../build/tranZPUterSW700_constraints.sdc | 2 +- CPLD/SW700/v1.3/tranZPUterSW700.vhd | 12 +- software/asm/MZ800_1Z_013B.asm | 2944 ++++++++++++++++ software/asm/MZ800_9Z_504M.asm | 3067 +++++++++++++++++ software/asm/MZ800_IOCS.asm | 1607 +++++++++ software/roms/9Z_504M.ROM | Bin 0 -> 8192 bytes software/roms/MZ800_1Z_013B.ORI | Bin 0 -> 4096 bytes software/roms/MZ800_1Z_013B.rom | Bin 0 -> 4096 bytes software/roms/MZ800_9Z_504M.ORI | Bin 0 -> 8192 bytes software/roms/MZ800_9Z_504M.rom | Bin 0 -> 5120 bytes software/roms/MZ800_CGROM.ORI | Bin 0 -> 4096 bytes software/roms/MZ800_CGROM_JP.ORI | Bin 0 -> 4096 bytes software/roms/MZ800_IOCS.ORI | Bin 0 -> 3072 bytes software/roms/MZ800_IOCS.rom | Bin 0 -> 3072 bytes software/roms/MZ800_IPL.rom | Bin 0 -> 16384 bytes software/tools/assemble_roms.sh | 6 +- 23 files changed, 8449 insertions(+), 609 deletions(-) create mode 100644 software/asm/MZ800_1Z_013B.asm create mode 100644 software/asm/MZ800_9Z_504M.asm create mode 100644 software/asm/MZ800_IOCS.asm create mode 100644 software/roms/9Z_504M.ROM create mode 100644 software/roms/MZ800_1Z_013B.ORI create mode 100644 software/roms/MZ800_1Z_013B.rom create mode 100644 software/roms/MZ800_9Z_504M.ORI create mode 100644 software/roms/MZ800_9Z_504M.rom create mode 100644 software/roms/MZ800_CGROM.ORI create mode 100644 software/roms/MZ800_CGROM_JP.ORI create mode 100644 software/roms/MZ800_IOCS.ORI create mode 100644 software/roms/MZ800_IOCS.rom create mode 100644 software/roms/MZ800_IPL.rom diff --git a/CPLD/SW/build/tranZPUterSW.qsf b/CPLD/SW/build/tranZPUterSW.qsf index 1474865..f7ef354 100644 --- a/CPLD/SW/build/tranZPUterSW.qsf +++ b/CPLD/SW/build/tranZPUterSW.qsf @@ -56,13 +56,18 @@ set_global_assignment -name MAX7000_DEVICE_IO_STANDARD LVTTL # Z80 Address Bus # =============== -set_location_assignment PIN_108 -to Z80_HI_ADDR[18] +set_location_assignment PIN_32 -to Z80_HI_ADDR[23] +set_location_assignment PIN_42 -to Z80_HI_ADDR[22] +set_location_assignment PIN_44 -to Z80_HI_ADDR[21] +set_location_assignment PIN_40 -to Z80_HI_ADDR[20] +set_location_assignment PIN_39 -to Z80_HI_ADDR[19] +set_location_assignment PIN_107 -to Z80_HI_ADDR[18] set_location_assignment PIN_102 -to Z80_HI_ADDR[17] -set_location_assignment PIN_107 -to Z80_HI_ADDR[16] -set_location_assignment PIN_110 -to Z80_HI_ADDR[15] -set_location_assignment PIN_111 -to Z80_HI_ADDR[14] -set_location_assignment PIN_112 -to Z80_HI_ADDR[13] -set_location_assignment PIN_114 -to Z80_HI_ADDR[12] +set_location_assignment PIN_108 -to Z80_HI_ADDR[16] +set_location_assignment PIN_110 -to Z80_RA_ADDR[15] +set_location_assignment PIN_111 -to Z80_RA_ADDR[14] +set_location_assignment PIN_112 -to Z80_RA_ADDR[13] +set_location_assignment PIN_114 -to Z80_RA_ADDR[12] set_location_assignment PIN_106 -to Z80_ADDR[15] set_location_assignment PIN_103 -to Z80_ADDR[14] set_location_assignment PIN_98 -to Z80_ADDR[13] @@ -118,17 +123,17 @@ set_location_assignment PIN_65 -to SVCREQn # ============ set_location_assignment PIN_41 -to CTL_WAITn set_location_assignment PIN_38 -to CTL_RFSHn -set_location_assignment PIN_31 -to CTL_CLKSLCT +set_location_assignment PIN_55 -to CTL_MBSEL set_location_assignment PIN_54 -to CTL_HALTn set_location_assignment PIN_128 -to CTLCLK set_location_assignment PIN_45 -to CTL_M1n -set_location_assignment PIN_55 -to CTL_BUSACKn +set_location_assignment PIN_31 -to CTL_BUSACKn set_location_assignment PIN_70 -to CTL_BUSRQn -set_location_assignment PIN_32 -to Z80_MEM[4] -set_location_assignment PIN_42 -to Z80_MEM[3] -set_location_assignment PIN_44 -to Z80_MEM[2] -set_location_assignment PIN_40 -to Z80_MEM[1] -set_location_assignment PIN_39 -to Z80_MEM[0] +#set_location_assignment PIN_32 -to Z80_MEM[4] +#set_location_assignment PIN_42 -to Z80_MEM[3] +#set_location_assignment PIN_44 -to Z80_MEM[2] +#set_location_assignment PIN_40 -to Z80_MEM[1] +#set_location_assignment PIN_39 -to Z80_MEM[0] # Z80 Control signals. # ==================== diff --git a/CPLD/SW/build/tranZPUterSW_constraints.sdc b/CPLD/SW/build/tranZPUterSW_constraints.sdc index 5540bcf..84582cf 100644 --- a/CPLD/SW/build/tranZPUterSW_constraints.sdc +++ b/CPLD/SW/build/tranZPUterSW_constraints.sdc @@ -75,36 +75,15 @@ create_clock -name {INCLK} -period 62.500 -waveform { 0.000 31.250 } [ get_po # Set Input Delay #************************************************************** -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_BUSACKn}] +set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_MBSEL}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_BUSRQn}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_WAITn}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_BUSRQn}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_WAITn}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[0]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[1]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[2]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[3]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[4]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[5]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[6]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[7]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[8]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[9]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[10]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[11]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[12]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[13]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[14]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[15]}] +set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[*]}] +set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HI_ADDR[*]}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_BUSACKn}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[0]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[1]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[2]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[3]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[4]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[5]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[6]}] -set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[7]}] +set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[*]}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HALTn}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_IORQn}] set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_M1n}] @@ -118,7 +97,7 @@ set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ # Set Output Delay #************************************************************** -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_CLKSLCT}] +set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_BUSACKn}] set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_HALTn}] set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_M1n}] set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_RFSHn}] @@ -133,47 +112,12 @@ set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {SYS #set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VADDR[12]}] #set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VADDR[13]}] #set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VMEM_CSn}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {OUTDATA[0]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {OUTDATA[1]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {OUTDATA[2]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {OUTDATA[3]}] +set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {OUTDATA[*]}] set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_BUSRQn}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[0]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[1]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[2]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[3]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[4]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[5]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[6]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[7]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[0]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[1]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[2]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[3]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[4]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[5]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[6]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[7]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[8]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[9]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[10]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[11]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[12]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[13]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[14]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[15]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[12]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[13]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[14]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[15]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[16]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[17]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[18]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MEM[0]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MEM[1]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MEM[2]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MEM[3]}] -set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MEM[4]}] +set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[*]}] +set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[*]}] +set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[*]}] +set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_RA_ADDR[*]}] set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_WAITn}] set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_INTn}] set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_NMIn}] @@ -208,12 +152,14 @@ set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}] #set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}] # For both configurations. -set_false_path -from {cpld512:cpldl512Toplevel|KEY_SUBSTITUTE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[4]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[3]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[2]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[1]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[0]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +set_false_path -from {cpld512:cpldl512Toplevel|KEY_SUBSTITUTE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +set_false_path -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +set_false_path -from {cpld512:cpldl512Toplevel|MODE_VIDEO_MZ80B} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_HI_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_LO_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +set_false_path -from {cpld512:cpldl512Toplevel|GRAM_PAGE_ENABLE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} + # For the video module interconnect clock. set_false_path -from [get_clocks {CTLCLK}] -to [get_clocks {INCLK}] diff --git a/CPLD/SW/tranZPUterSW.vhd b/CPLD/SW/tranZPUterSW.vhd index 33be388..a2ec421 100644 --- a/CPLD/SW/tranZPUterSW.vhd +++ b/CPLD/SW/tranZPUterSW.vhd @@ -3,7 +3,7 @@ -- Name: tranZPUterSW.vhd -- Created: June 2020 -- Author(s): Philip Smart --- Description: tranZPUter SW v2.1 CPLD logic definition file. +-- Description: tranZPUter SW v2.1 - v2.2 CPLD logic definition file. -- This module contains the definition of the logic used in v1.0-v1.1 of the tranZPUterSW -- project plus enhancements. -- @@ -30,7 +30,11 @@ -- onto the output that would normally be driven by a K64F. This output -- is then divided down to act as the secondary clock. When a mode switch -- is made to MZ700 mode the frequency automatically changes. --- +-- Mar 2021 - Updated to enable better compatibility with the Sharp MZ-800. +-- Mar 2021 - Better control of the external Asyn BUSRQ/BUSACK was needed, bringing in +-- Synchronize with the SW700 development. +-- the async K64F CTL_BUSRQ into the Z80 clocked domain and adjustment of +-- mux lines. -- --------------------------------------------------------------------------------------------------------- -- This source file is free software: you can redistribute it and-or modify @@ -58,56 +62,56 @@ entity cpld512 is --); port ( -- Z80 Address and Data. - Z80_HI_ADDR : out std_logic_vector(18 downto 12); - Z80_ADDR : inout std_logic_vector(15 downto 0); - Z80_DATA : inout std_logic_vector( 7 downto 0); + Z80_HI_ADDR : inout std_logic_vector(23 downto 16); -- Hi address. These are the upper bank bits allowing 512K of address space. They are directly set by the K64F when accessing RAM or FPGA and set by the FPGA according to memory mode. + Z80_RA_ADDR : out std_logic_vector(15 downto 12); -- Row address - RAM is subdivided into 4K blocks which can be remapped as needed. This is required for the MZ80B emulation where memory changes location according to mode. + Z80_ADDR : inout std_logic_vector(15 downto 0); + Z80_DATA : inout std_logic_vector( 7 downto 0); -- Z80 Control signals. - Z80_BUSRQn : out std_logic; - Z80_BUSACKn : in std_logic; - Z80_INTn : inout std_logic; - Z80_IORQn : in std_logic; - Z80_MREQn : inout std_logic; - Z80_NMIn : inout std_logic; - Z80_RDn : in std_logic; - Z80_WRn : in std_logic; - Z80_RESETn : in std_logic; -- NB. The CPLD inverts the GCLRn pin, so active negative on the mainboard, active positive inside the CPLD. - Z80_HALTn : in std_logic; - Z80_WAITn : out std_logic; - Z80_M1n : in std_logic; - Z80_RFSHn : in std_logic; - Z80_CLK : out std_logic; + Z80_BUSRQn : out std_logic; + Z80_BUSACKn : in std_logic; + Z80_INTn : inout std_logic; + Z80_IORQn : in std_logic; + Z80_MREQn : inout std_logic; + Z80_NMIn : inout std_logic; + Z80_RDn : in std_logic; + Z80_WRn : in std_logic; + Z80_RESETn : in std_logic; -- NB. The CPLD inverts the GCLRn pin, so active negative on the mainboard, active positive inside the CPLD. + Z80_HALTn : in std_logic; + Z80_WAITn : out std_logic; + Z80_M1n : in std_logic; + Z80_RFSHn : in std_logic; + Z80_CLK : out std_logic; -- K64F control signals. - CTL_BUSACKn : in std_logic; - CTL_BUSRQn : in std_logic; - CTL_HALTn : out std_logic; - CTL_M1n : out std_logic; - CTL_RFSHn : out std_logic; - CTL_WAITn : in std_logic; - SVCREQn : out std_logic; - Z80_MEM : out std_logic_vector(4 downto 0); + CTL_MBSEL : in std_logic; -- Select mainboard, 1 = mainboard, 0 = tranzputer bus. + CTL_BUSRQn : in std_logic; + CTL_BUSACKn : out std_logic; -- Combined BUSACK signal to the K64F + CTL_HALTn : out std_logic; + CTL_M1n : out std_logic; + CTL_RFSHn : out std_logic; + CTL_WAITn : in std_logic; + SVCREQn : out std_logic; -- Mainboard signals which are blended with K64F signals to activate corresponding Z80 functionality. - SYS_BUSACKn : out std_logic; - SYS_BUSRQn : in std_logic; - SYS_WAITn : in std_logic; - SYS_WRn : out std_logic; - SYS_RDn : out std_logic; + SYS_BUSACKn : out std_logic; + SYS_BUSRQn : in std_logic; + SYS_WAITn : in std_logic; + SYS_WRn : out std_logic; + SYS_RDn : out std_logic; -- RAM control. - RAM_CSn : out std_logic; - RAM_OEn : out std_logic; - RAM_WEn : out std_logic; + RAM_CSn : out std_logic; + RAM_OEn : out std_logic; + RAM_WEn : out std_logic; -- Graphics Board I/O and Memory Select. - INCLK : in std_logic; - OUTDATA : out std_logic_vector(3 downto 0); + INCLK : in std_logic; + OUTDATA : out std_logic_vector(3 downto 0); -- Clocks, system and K64F generated. - SYSCLK : in std_logic; - CTLCLK : in std_logic; - CTL_CLKSLCT : out std_logic + SYSCLK : in std_logic; -- Mainboard system clock. + CTLCLK : in std_logic -- K64F generated secondary CPU clock. ); end entity; @@ -139,33 +143,33 @@ architecture rtl of cpld512 is signal MODE_CPLD_MZ80B : std_logic; signal MODE_CPLD_MZ2000 : std_logic; signal MODE_CPLD_SWITCH : std_logic; - signal MODE_CPLD_MB_VIDEOn : std_logic; -- Mainboard video, 0 = enabled, 1 = disabled. - signal CPLD_CFG_DATA : std_logic_vector(7 downto 0); -- CPLD Configuration register. - signal CPLD_INFO_DATA : std_logic_vector(7 downto 0); -- CPLD status value. - signal VIDEOMODULE_PRESENT : std_logic; -- Automatic flag which is set if the serializer becomes active. + signal MODE_CPLD_MB_VIDEOn : std_logic; -- Mainboard video, 0 = enabled, 1 = disabled. + signal CPLD_CFG_DATA : std_logic_vector(7 downto 0); -- CPLD Configuration register. + signal CPLD_INFO_DATA : std_logic_vector(7 downto 0); -- CPLD status value. + signal VIDEOMODULE_PRESENT : std_logic; -- Automatic flag which is set if the serializer becomes active. -- IO Decode signals. - signal CS_IO_6XXn : std_logic; -- IO decode for the 0x60-0x6f region used by the CPLD. - signal CS_MEM_CFGn : std_logic; -- Select for the memory mode latch. - signal CS_SCK_CTLCLKn : std_logic; -- Select for setting the K64F clock as the active Z80 clock. - signal CS_SCK_SYSCLKn : std_logic; -- Select for setting the Mainboard clock as the active Z80 clock. - signal CS_SCK_RDn : std_logic; -- Select to read which clock is active. - signal CS_CPLD_CFGn : std_logic; -- Select to set the CPLD configuration register. - signal CS_CPLD_INFOn : std_logic; -- Select to read the CPLD information register. - signal CS_VIDEOn : std_logic; -- Primary select of the FPGA video logic, used to enable control signals in the memory management process. - signal CS_VIDEO_MEMn : std_logic; -- Select to read/write video memory according to mode. - signal CS_VIDEO_IOn : std_logic; -- Select to read/write video IO registers according to mode. - signal CS_VIDEO_RDn : std_logic; -- Select to read video memory and video IO registers according to mode. - signal CS_VIDEO_WRn : std_logic; -- Select to write video memory and video IO registers according to mode. - signal MEM_MODE_LATCH : std_logic_vector(4 downto 0); -- Register to store the active memory mode. - signal MEM_MODE_DATA : std_logic_vector(7 downto 0); -- Scratch signal to form an 8 bit read of the memory mode register. + signal CS_IO_6XXn : std_logic; -- IO decode for the 0x60-0x6f region used by the CPLD. + signal CS_MEM_CFGn : std_logic; -- Select for the memory mode latch. + signal CS_SCK_CTLCLKn : std_logic; -- Select for setting the K64F clock as the active Z80 clock. + signal CS_SCK_SYSCLKn : std_logic; -- Select for setting the Mainboard clock as the active Z80 clock. + signal CS_SCK_RDn : std_logic; -- Select to read which clock is active. + signal CS_CPLD_CFGn : std_logic; -- Select to set the CPLD configuration register. + signal CS_CPLD_INFOn : std_logic; -- Select to read the CPLD information register. + signal CS_VIDEOn : std_logic; -- Primary select of the FPGA video logic, used to enable control signals in the memory management process. + signal CS_VIDEO_MEMn : std_logic; -- Select to read/write video memory according to mode. + signal CS_VIDEO_IOn : std_logic; -- Select to read/write video IO registers according to mode. + signal CS_VIDEO_RDn : std_logic; -- Select to read video memory and video IO registers according to mode. + signal CS_VIDEO_WRn : std_logic; -- Select to write video memory and video IO registers according to mode. + signal MEM_MODE_LATCH : std_logic_vector(4 downto 0); -- Register to store the active memory mode. + signal MEM_MODE_DATA : std_logic_vector(7 downto 0); -- Scratch signal to form an 8 bit read of the memory mode register. -- SR (LS279) state symbols. signal SYSCLK_Q : std_logic; signal CTLCLK_Q : std_logic; -- - signal DISABLE_BUSn : std_logic; -- Signal to disable access to the mainboard (= 0) via the SYS_BUSACKn signal which tri-states the mainboard logic. - signal SYS_BUSACKni : std_logic := '0'; -- Signal to hold the current state of the SYS_BUSACKn signal used to activate/tri-state the mainboard logic. + signal DISABLE_BUSn : std_logic; -- Signal to disable access to the mainboard (= 0) via the SYS_BUSACKn signal which tri-states the mainboard logic. + signal SYS_BUSACKni : std_logic := '0'; -- Signal to hold the current state of the SYS_BUSACKn signal used to activate/tri-state the mainboard logic. -- CPU Frequency select logic based on Flip Flops and gates. signal SCK_CTLSELn : std_logic; @@ -179,27 +183,33 @@ architecture rtl of cpld512 is signal OUTBUF : std_logic_vector(3 downto 0); -- Video module signal mirrors. - signal MODE_VIDEO_MZ80A : std_logic := '1'; -- The machine is running in MZ80A mode. - signal MODE_VIDEO_MZ700 : std_logic := '0'; -- The machine is running in MZ700 mode. - signal MODE_VIDEO_MZ800 : std_logic := '0'; -- The machine is running in MZ800 mode. - signal MODE_VIDEO_MZ80B : std_logic := '0'; -- The machine is running in MZ80B mode. - signal MODE_VIDEO_MZ80K : std_logic := '0'; -- The machine is running in MZ80K mode. - signal MODE_VIDEO_MZ80C : std_logic := '0'; -- The machine is running in MZ80C mode. - signal MODE_VIDEO_MZ1200 : std_logic := '0'; -- The machine is running in MZ1200 mode. - signal MODE_VIDEO_MZ2000 : std_logic := '0'; -- The machine is running in MZ2000 mode. - signal GRAM_PAGE_ENABLE : std_logic; -- Graphics mode page enable. - signal MZ80B_VRAM_HI_ADDR : std_logic; -- Video RAM located at D000:FFFF when high. - signal MZ80B_VRAM_LO_ADDR : std_logic; -- Video RAM located at 5000:7FFF when high. - signal CS_FB_VMn : std_logic; -- Chip Select for the Video Mode register. - signal CS_FB_PAGEn : std_logic; -- Chip Select for the Page select register. - signal CS_IO_DXXn : std_logic; -- Chip select for block 00:0F - signal CS_IO_EXXn : std_logic; -- Chip select for block E0:EF - signal CS_IO_FXXn : std_logic; -- Chip select for block F0:FF - signal CS_80B_PIOn : std_logic; -- Chip select for MZ80B PIO when in MZ80B mode. + signal MODE_VIDEO_MZ80A : std_logic := '1'; -- The machine is running in MZ80A mode. + signal MODE_VIDEO_MZ700 : std_logic := '0'; -- The machine is running in MZ700 mode. + signal MODE_VIDEO_MZ800 : std_logic := '0'; -- The machine is running in MZ800 mode. + signal MODE_VIDEO_MZ80B : std_logic := '0'; -- The machine is running in MZ80B mode. + signal MODE_VIDEO_MZ80K : std_logic := '0'; -- The machine is running in MZ80K mode. + signal MODE_VIDEO_MZ80C : std_logic := '0'; -- The machine is running in MZ80C mode. + signal MODE_VIDEO_MZ1200 : std_logic := '0'; -- The machine is running in MZ1200 mode. + signal MODE_VIDEO_MZ2000 : std_logic := '0'; -- The machine is running in MZ2000 mode. + signal GRAM_PAGE_ENABLE : std_logic; -- Graphics mode page enable. + signal MZ80B_VRAM_HI_ADDR : std_logic; -- Video RAM located at D000:FFFF when high. + signal MZ80B_VRAM_LO_ADDR : std_logic; -- Video RAM located at 5000:7FFF when high. + signal CS_FB_VMn : std_logic; -- Chip Select for the Video Mode register. + signal CS_FB_PAGEn : std_logic; -- Chip Select for the Page select register. + signal CS_IO_DXXn : std_logic; -- Chip select for block 00:0F + signal CS_IO_EXXn : std_logic; -- Chip select for block E0:EF + signal CS_IO_FXXn : std_logic; -- Chip select for block F0:FF + signal CS_80B_PIOn : std_logic; -- Chip select for MZ80B PIO when in MZ80B mode. -- Z80 Wait Insert generator when I/O ports in region > 0XE0 are accessed to give the K64F time to proces them. --signal REQ_WAITn : std_logic; + -- Internal control signals. + signal Z80_HI_ADDRi : std_logic_vector(23 downto 16); -- Hi address. These are the upper bank bits allowing 512K of address space. They are directly set by the K64F when accessing RAM or FPGA and set by the FPGA according to memory mode. + signal Z80_RA_ADDRi : std_logic_vector(15 downto 12); -- Row address - RAM is subdivided into 4K blocks which can be remapped as needed. This is required for the MZ80B emulation where memory changes location according to mode. + signal CTL_BUSACKni : std_logic; -- Buffered BUSACK signal to the K64F to indicate it has control of the bus. + signal CTL_BUSRQni : std_logic; -- Buffered BUSRQ signal. + -- RAM select and write signals. signal RAM_OEni : std_logic; signal RAM_CSni : std_logic; @@ -229,31 +239,42 @@ begin -- The mode can be changed by a Z80 transaction write into the register and it is acted upon if the mode switches between differing values. The Z80 write is typically used -- by host software such as RFS. -- - -- [2:0] - Mode/emulated machine. - -- 000 = MZ-80K - -- 001 = MZ-80C - -- 010 = MZ-1200 - -- 011 = MZ-80A - -- 100 = MZ-700 - -- 101 = MZ-800 - -- 110 = MZ-80B - -- 111 = MZ-2000 - -- [3] - Mainboard Video - 1 = Enable, 0 = Disable - This flag allows Z-80 transactions in the range D000:DFFF to be directed to the mainboard. When disabled all transactions - -- can only be seen by the FPGA video logic. The FPGA uses this flag to enable/disable it's functionality. - -- [6:4] = Mainboard/CPU clock. - -- 000 = Sharp MZ80A 2MHz System Clock. - -- 001 = Sharp MZ80B 4MHz System Clock. - -- 010 = Sharp MZ700 3.54MHz System Clock. - -- 011 -111 = Reserved, defaults to 2MHz System Clock. + -- [2:0] - R/W - Mode/emulated machine. + -- 000 = MZ-80K + -- 001 = MZ-80C + -- 010 = MZ-1200 + -- 011 = MZ-80A + -- 100 = MZ-700 + -- 101 = MZ-800 + -- 110 = MZ-80B + -- 111 = MZ-2000 + -- [3] - R/W - Mainboard Video - 0 = Enable, 1 = Disable - This flag allows Z-80 transactions in the range D000:DFFF to be directed to the mainboard. When disabled all transactions + -- can only be seen by the FPGA video logic. The FPGA uses this flag to enable/disable it's functionality. + --*[4] - R/W - Enable WAIT state during frame display period. 1 = Enable, 0 = Disable (default). The flag enables Z80 WAIT assertion during the frame display period. Most video modes + -- use double buffering so this isnt needed, but use of direct writes to the frame buffer in 8 colour mode (ie. 640x200 or 320x200 8 colour) there + -- is not enough memory to double buffer so potentially there could be tear or snow, hence this optional wait generator. + -- [6:5] - R/W - Mainboard/CPU clock. + -- 000 = Sharp MZ80A 2MHz System Clock. + -- 001 = Sharp MZ80B 4MHz System Clock. + -- 010 = Sharp MZ700 3.54MHz System Clock. + -- 011 -111 = Reserved, defaults to 2MHz System Clock. + --*[7] - R/W - Preserve configuration over reset (=1) or set to default on reset (=0). + -- * = SW700 v1.3 only, not used in other CPLD versions. -- - MACHINEMODE: process( Z80_CLKi, Z80_RESETn, CS_CPLD_CFGn, CS_CPLD_INFOn, Z80_ADDR, Z80_DATA ) + MACHINEMODE: process( Z80_CLKi, Z80_RESETn, CS_CPLD_CFGn, CPLD_CFG_DATA, CS_CPLD_INFOn, Z80_DATA ) begin if(Z80_RESETn = '0') then MODE_CPLD_SWITCH <= '0'; - CPLD_CFG_DATA <= "00000011"; -- Default to Sharp MZ80A + if CPLD_CFG_DATA(7) = '0' then + if CPLD_HOST_HW = MODE_MZ800 then + CPLD_CFG_DATA <= "10001101"; -- Enable Sharp MZ-800 host setting, mainboard video unused, wait state unused. + else -- Default to MZ-80A + CPLD_CFG_DATA <= "10000011"; -- Default to Sharp MZ80A + end if; + end if; - elsif(Z80_CLKi'event and Z80_CLKi = '1') then + elsif(rising_edge(Z80_CLKi)) then -- Write to config register. if(CS_CPLD_CFGn = '0' and Z80_WRn = '0') then @@ -271,20 +292,19 @@ begin end if; end process; - -- Memory mode latch. This latch stores the current memory mode (or Bank Paging Scheme) according to the running software. -- MEMORYMODE: process( Z80_CLKi, Z80_RESETn, CS_MEM_CFGn, Z80_IORQn, Z80_WRn, Z80_ADDR, Z80_DATA ) - variable mz700_LOWER_RAM : std_logic; - variable mz700_UPPER_RAM : std_logic; - variable mz700_INHIBIT : std_logic; + variable mz700_LOWER_RAM : std_logic; + variable mz700_UPPER_RAM : std_logic; + variable mz700_INHIBIT : std_logic; begin if(Z80_RESETn = '0') then - MEM_MODE_LATCH <= "00000"; - mz700_LOWER_RAM := '0'; - mz700_UPPER_RAM := '0'; - mz700_INHIBIT := '0'; + MEM_MODE_LATCH <= "00000"; + mz700_LOWER_RAM := '0'; + mz700_UPPER_RAM := '0'; + mz700_INHIBIT := '0'; elsif (CS_MEM_CFGn = '0' and Z80_WRn = '0') then MEM_MODE_LATCH <= Z80_DATA(4 downto 0); @@ -364,209 +384,221 @@ begin end process; -- Process to map host keyboard to realise compatibility with other Sharp machines. - -- Currently the host is the Sharp MZ-80A Target (emulated) machines will be mapped such that the MZ-80A keyboard + -- Currently the host can be a Sharp MZ-80A or MZ-800. Target (emulated) machines will be mapped accordingly. -- will appear as the target keyboard. - KEYMAPPER: process( Z80_CLKi, Z80_RESETn, CS_MEM_CFGn, Z80_IORQn, Z80_ADDR, Z80_DATA ) - begin + USEKEYMAPPER: if CPLD_HOST_HW = MODE_MZ80A generate - if Z80_RESETn = '0' then - KEY_SUBSTITUTE <= '0'; - KEY_SWEEP <= '0'; - MB_STATE <= 0; - MB_BUSRQn <= '1'; - MB_MREQn <= '1'; - MB_WRITE_STROBE <= '0'; - MB_READ_KEYS <= '0'; - MB_WAITn <= '1'; - MB_ADDR <= (others => '0'); - MB_DELAY_TICKS <= (others => '1'); - MB_DELAY_MS <= (others => '0'); - MB_KEY_STROBE <= (others => '0'); - KEY_STROBE <= (others => '0'); - KEY_STROBE_LAST <= (others => '0'); + KEYMAPPER: process( Z80_CLKi, Z80_RESETn, CS_MEM_CFGn, Z80_IORQn, Z80_ADDR, Z80_DATA ) + begin - elsif Z80_CLKi'event and Z80_CLKi = '1' then + if Z80_RESETn = '0' then + KEY_SUBSTITUTE <= '0'; + KEY_SWEEP <= '0'; + MB_STATE <= 0; + MB_BUSRQn <= '1'; + MB_MREQn <= '1'; + MB_WRITE_STROBE <= '0'; + MB_READ_KEYS <= '0'; + MB_WAITn <= '1'; + MB_ADDR <= (others => '0'); + MB_DELAY_TICKS <= (others => '1'); + MB_DELAY_MS <= (others => '0'); + MB_KEY_STROBE <= (others => '0'); + KEY_STROBE <= (others => '0'); + KEY_STROBE_LAST <= (others => '0'); - -- When inactive, wait for a Z80 I/O transaction that needs writeback. - -- - if MODE_CPLD_MZ700 = '1' then + elsif Z80_CLKi'event and Z80_CLKi = '1' then - -- Auto scanning state machine. When the MZ700 isnt scanning the keys this FSM scans them to be ready - -- to respond to events such as BREAK key detection. Normally the FSM wont run as the MZ700 scans the keys in - -- software but when the MZ700 runs some kinds of software the scans stop and occasionally the BREAK/SHIFT line 9 is scanned. - -- Under these circumstances the FSM will make a full sweep of the keys. + -- When inactive, wait for a Z80 I/O transaction that needs writeback. -- - -- Configurable delay, a tick by tick timer and a millisecond timer, halts all actions whilst the timer > 0. - if MB_DELAY_TICKS /= 0 or MB_DELAY_MS /= 0 then + if CPLD_HOST_HW = MODE_MZ80A and MODE_CPLD_MZ700 = '1' then - if MB_DELAY_TICKS = 0 and MB_DELAY_MS /= 0 then - MB_DELAY_TICKS <= X"DFC"; -- 1ms with a 3.58MHz clock. - MB_DELAY_MS <= MB_DELAY_MS - 1; - else - MB_DELAY_TICKS <= MB_DELAY_TICKS - 1; - end if; - - -- If the Z80 Bus has not been requested and we need to make a key sweep, request the bus and start the sweep. - elsif Z80_MREQn = '1' and MB_BUSRQn = '1' and MB_WAITn = '1' and KEY_SWEEP = '1' and KEY_SUBSTITUTE = '0' then - MB_BUSRQn <= '0'; - - -- When the Z80 bus is available, run the FSM. - elsif MB_BUSRQn = '0' and Z80_BUSACKn = '0' then - - -- Move along the state machine, next state can be overriden if required. + -- Auto scanning state machine. When the MZ700 isnt scanning the keys this FSM scans them to be ready + -- to respond to events such as BREAK key detection. Normally the FSM wont run as the MZ700 scans the keys in + -- software but when the MZ700 runs some kinds of software the scans stop and occasionally the BREAK/SHIFT line 9 is scanned. + -- Under these circumstances the FSM will make a full sweep of the keys. -- - if MB_STATE = 6 then - MB_STATE <= 0; - else - MB_STATE <= MB_STATE+1; - end if; + -- Configurable delay, a tick by tick timer and a millisecond timer, halts all actions whilst the timer > 0. + if MB_DELAY_TICKS /= 0 or MB_DELAY_MS /= 0 then - -- FSM. - case MB_STATE is - -- Setup to write the strobe value to PPI A. - when 0 => - MB_ADDR <= X"E000"; - KEY_DATA <= "1111" & MB_KEY_STROBE; - - -- Allow at least 1 cycles for the MREQ signal to settle. - when 1 => - MB_MREQn <= '0'; - - -- Allow at least 1 cycle for the write pulse. - when 2 => - MB_WRITE_STROBE <= '1'; - - -- Terminate write pulse. - when 3 => - MB_MREQn <= '1'; - MB_WRITE_STROBE <= '0'; - - -- Setup for a read of the key data from PPI B. - when 4 => - MB_ADDR <= X"E001"; - - -- Allow at least 2 cycles for the data to become available. - when 5 => - MB_MREQn <= '0'; - MB_READ_KEYS <= '1'; - - -- Read the key data into the matrix for later mapping. - when 6 => - KEY_MATRIX(to_integer(unsigned(MB_KEY_STROBE))) <= Z80_DATA; - MB_MREQn <= '1'; - MB_READ_KEYS <= '0'; - - if unsigned(MB_KEY_STROBE) = 9 then - MB_KEY_STROBE <= (others => '0'); - MB_DELAY_MS <= X"FA"; -- 250ms delay between key sweeps with a 3.58MHz clock to prevent excessive scanning. - KEY_SWEEP <= '0'; - MB_BUSRQn <= '1'; - else - MB_KEY_STROBE <= MB_KEY_STROBE + 1; - MB_BUSRQn <= '1'; - end if; - - when others => - MB_STATE <= 0; - end case; - end if; - - -- When the Z80 isnt tri-stated process the memory operations and act on required triggers. - -- - if MB_BUSRQn = '1' and Z80_BUSACKn = '1' then - -- Detect a strobe output write and store it - this is used as the index into the key matrix for each read operation. - if(Z80_MREQn = '0' and Z80_ADDR(15 downto 0) = X"E000" and Z80_DATA(7) = '1') then - KEY_STROBE <= Z80_DATA(3 downto 0); - end if; - - -- On a keyscan read data into the matrix and raise the substitue flag. This flag will disable the mainboard (tri-state it) so that the data lines are not driven. The mapped - -- data is then output on the data bus by the CPLD which the Z80 reads. - if(Z80_MREQn = '0' and Z80_ADDR(15 downto 0) = X"E001") then - - -- If this is the first loop, set a 1 cycle wait to allow us to read in the scanned data before overriding with the mapped data. The Z80 cycle is short so without the wait - -- we cant reliably read the data being output from the 8255. - if MB_WAITn = '1' and KEY_SUBSTITUTE = '0' then - MB_WAITn <= '0'; - MB_BUSRQn <= '1'; + if MB_DELAY_TICKS = 0 and MB_DELAY_MS /= 0 then + MB_DELAY_TICKS <= X"DFC"; -- 1ms with a 3.58MHz clock. + MB_DELAY_MS <= MB_DELAY_MS - 1; else - -- 2nd cycle we release the WAIT state and override the data being output by the 8255 with the mapped equivalent. - MB_WAITn <= '1'; - KEY_SUBSTITUTE <= '1'; - - -- On the 2nd loop the data from the 8255 key scan has settled on the bus so can be captured. - if KEY_SUBSTITUTE = '0' then - KEY_MATRIX(to_integer(unsigned(KEY_STROBE))) <= Z80_DATA; - end if; - - -- Remember last key strobe as we need to detect a scan to the same row more than once, this is typically used for BREAK detection or single key detection. - -- In these cases we make an automated sweep of the entire keyboard as keys on the host are spread out on different strobe lines whereas the machine we are mapping to - -- has them on one strobe line. - KEY_STROBE_LAST <= KEY_STROBE; - if KEY_STROBE_LAST = KEY_STROBE and KEY_SWEEP = '0' then - KEY_SWEEP <= '1'; - end if; + MB_DELAY_TICKS <= MB_DELAY_TICKS - 1; end if; - -- Actual keyboard mapping. The Sharp MZ-80A key codes are scanned into a 10x8 matrix and then this matrix is indexed to extract the keycodes for the machine we - -- are being compatible with. + -- If the Z80 Bus has not been requested and we need to make a key sweep, request the bus and start the sweep. + elsif Z80_MREQn = '1' and MB_BUSRQn = '1' and MB_WAITn = '1' and KEY_SWEEP = '1' and KEY_SUBSTITUTE = '0' then + MB_BUSRQn <= '0'; + + -- When the Z80 bus is available, run the FSM. + elsif MB_BUSRQn = '0' and Z80_BUSACKn = '0' then + + -- Move along the state machine, next state can be overriden if required. -- - -- MZ-80A Keyboard -> MZ-700 mapping. - if MODE_CPLD_MZ700 = '1' then - case KEY_STROBE is - -- D7 D6 D5 D4 D3 D2 D1 D0 - when "0000" => - KEY_DATA <= '1' & KEY_MATRIX(0)(7) & KEY_MATRIX(7)(4) & KEY_MATRIX(0)(1) & '1' & KEY_MATRIX(6)(2) & KEY_MATRIX(6)(3) & KEY_MATRIX(7)(3); -- 1 - when "0001" => - KEY_DATA <= KEY_MATRIX(3)(5) & KEY_MATRIX(1)(0) & KEY_MATRIX(6)(4) & KEY_MATRIX(6)(5) & KEY_MATRIX(7)(2) & '1' & '1' & '1' ; -- 2 - when "0010" => - KEY_DATA <= KEY_MATRIX(1)(4) & KEY_MATRIX(2)(5) & KEY_MATRIX(2)(2) & KEY_MATRIX(3)(4) & KEY_MATRIX(4)(4) & KEY_MATRIX(3)(1) & KEY_MATRIX(1)(5) & KEY_MATRIX(2)(1); -- 3 - when "0011" => - KEY_DATA <= KEY_MATRIX(4)(5) & KEY_MATRIX(4)(3) & KEY_MATRIX(5)(2) & KEY_MATRIX(5)(3) & KEY_MATRIX(5)(0) & KEY_MATRIX(4)(1) & KEY_MATRIX(5)(4) & KEY_MATRIX(5)(5); -- 4 - when "0100" => - KEY_DATA <= KEY_MATRIX(1)(3) & KEY_MATRIX(3)(0) & KEY_MATRIX(2)(0) & KEY_MATRIX(2)(3) & KEY_MATRIX(2)(4) & KEY_MATRIX(3)(2) & KEY_MATRIX(3)(3) & KEY_MATRIX(4)(2); -- 5 - when "0101" => - KEY_DATA <= KEY_MATRIX(1)(6) & KEY_MATRIX(1)(7) & KEY_MATRIX(2)(6) & KEY_MATRIX(2)(7) & KEY_MATRIX(3)(6) & KEY_MATRIX(3)(7) & KEY_MATRIX(4)(6) & KEY_MATRIX(4)(7); -- 6 - when "0110" => - KEY_DATA <= KEY_MATRIX(7)(6) & KEY_MATRIX(6)(7) & KEY_MATRIX(6)(6) & KEY_MATRIX(4)(0) & KEY_MATRIX(5)(7) & KEY_MATRIX(5)(6) & KEY_MATRIX(5)(1) & KEY_MATRIX(6)(0); -- 7 - when "0111" => - KEY_DATA <= KEY_MATRIX(8)(6) & KEY_MATRIX(9)(6) & KEY_MATRIX(8)(7) & KEY_MATRIX(8)(3) & KEY_MATRIX(9)(4) & KEY_MATRIX(8)(4) & KEY_MATRIX(7)(0) & KEY_MATRIX(6)(1); -- 8 - when "1000" => - KEY_DATA <= KEY_MATRIX(7)(7) & KEY_MATRIX(1)(2) & '1' & '1' & '1' & '1' & '1' & KEY_MATRIX(0)(0); -- 9 - when "1001" => - KEY_DATA <= KEY_MATRIX(8)(2) & KEY_MATRIX(8)(0) & KEY_MATRIX(8)(1) & KEY_MATRIX(9)(0) & KEY_MATRIX(9)(2) & '1' & '1' & '1' ; -- 10 - when others => - KEY_DATA <= "11111111"; - end case; + if MB_STATE = 6 then + MB_STATE <= 0; + else + MB_STATE <= MB_STATE+1; end if; + + -- FSM. + case MB_STATE is + -- Setup to write the strobe value to PPI A. + when 0 => + MB_ADDR <= X"E000"; + KEY_DATA <= "1111" & MB_KEY_STROBE; + + -- Allow at least 1 cycles for the MREQ signal to settle. + when 1 => + MB_MREQn <= '0'; + + -- Allow at least 1 cycle for the write pulse. + when 2 => + MB_WRITE_STROBE <= '1'; + + -- Terminate write pulse. + when 3 => + MB_MREQn <= '1'; + MB_WRITE_STROBE <= '0'; + + -- Setup for a read of the key data from PPI B. + when 4 => + MB_ADDR <= X"E001"; + + -- Allow at least 2 cycles for the data to become available. + when 5 => + MB_MREQn <= '0'; + MB_READ_KEYS <= '1'; + + -- Read the key data into the matrix for later mapping. + when 6 => + KEY_MATRIX(to_integer(unsigned(MB_KEY_STROBE))) <= Z80_DATA; + MB_MREQn <= '1'; + MB_READ_KEYS <= '0'; + + if unsigned(MB_KEY_STROBE) = 9 then + MB_KEY_STROBE <= (others => '0'); + MB_DELAY_MS <= X"FA"; -- 250ms delay between key sweeps with a 3.58MHz clock to prevent excessive scanning. + KEY_SWEEP <= '0'; + MB_BUSRQn <= '1'; + else + MB_KEY_STROBE <= MB_KEY_STROBE + 1; + MB_BUSRQn <= '1'; + end if; + + when others => + MB_STATE <= 0; + end case; end if; - -- When the Z80_MREQn goes inactive, the keyboard read has completed so clear the substitute flag which in turn allows normal bus operations. + -- When the Z80 isnt tri-stated process the memory operations and act on required triggers. -- - if(KEY_SUBSTITUTE = '1' and Z80_MREQn = '1') then - KEY_SUBSTITUTE <= '0'; + if MB_BUSRQn = '1' and Z80_BUSACKn = '1' then + -- Detect a strobe output write and store it - this is used as the index into the key matrix for each read operation. + if(Z80_MREQn = '0' and Z80_ADDR(15 downto 0) = X"E000" and Z80_DATA(7) = '1') then + KEY_STROBE <= Z80_DATA(3 downto 0); + end if; + + -- On a keyscan read data into the matrix and raise the substitue flag. This flag will disable the mainboard (tri-state it) so that the data lines are not driven. The mapped + -- data is then output on the data bus by the CPLD which the Z80 reads. + if(Z80_MREQn = '0' and Z80_ADDR(15 downto 0) = X"E001") then + + -- If this is the first loop, set a 1 cycle wait to allow us to read in the scanned data before overriding with the mapped data. The Z80 cycle is short so without the wait + -- we cant reliably read the data being output from the 8255. + if MB_WAITn = '1' and KEY_SUBSTITUTE = '0' then + MB_WAITn <= '0'; + MB_BUSRQn <= '1'; + else + -- 2nd cycle we release the WAIT state and override the data being output by the 8255 with the mapped equivalent. + MB_WAITn <= '1'; + KEY_SUBSTITUTE <= '1'; + + -- On the 2nd loop the data from the 8255 key scan has settled on the bus so can be captured. + if KEY_SUBSTITUTE = '0' then + KEY_MATRIX(to_integer(unsigned(KEY_STROBE))) <= Z80_DATA; + end if; + + -- Remember last key strobe as we need to detect a scan to the same row more than once, this is typically used for BREAK detection or single key detection. + -- In these cases we make an automated sweep of the entire keyboard as keys on the host are spread out on different strobe lines whereas the machine we are mapping to + -- has them on one strobe line. + KEY_STROBE_LAST <= KEY_STROBE; + if KEY_STROBE_LAST = KEY_STROBE and KEY_SWEEP = '0' then + KEY_SWEEP <= '1'; + end if; + end if; + + -- Actual keyboard mapping. The Sharp MZ-80A key codes are scanned into a 10x8 matrix and then this matrix is indexed to extract the keycodes for the machine we + -- are being compatible with. + -- + -- MZ-80A Keyboard -> MZ-700 mapping. + if MODE_CPLD_MZ700 = '1' then + case KEY_STROBE is + -- D7 D6 D5 D4 D3 D2 D1 D0 + when "0000" => + KEY_DATA <= '1' & KEY_MATRIX(0)(7) & KEY_MATRIX(7)(4) & KEY_MATRIX(0)(1) & '1' & KEY_MATRIX(6)(2) & KEY_MATRIX(6)(3) & KEY_MATRIX(7)(3); -- 1 + when "0001" => + KEY_DATA <= KEY_MATRIX(3)(5) & KEY_MATRIX(1)(0) & KEY_MATRIX(6)(4) & KEY_MATRIX(6)(5) & KEY_MATRIX(7)(2) & '1' & '1' & '1' ; -- 2 + when "0010" => + KEY_DATA <= KEY_MATRIX(1)(4) & KEY_MATRIX(2)(5) & KEY_MATRIX(2)(2) & KEY_MATRIX(3)(4) & KEY_MATRIX(4)(4) & KEY_MATRIX(3)(1) & KEY_MATRIX(1)(5) & KEY_MATRIX(2)(1); -- 3 + when "0011" => + KEY_DATA <= KEY_MATRIX(4)(5) & KEY_MATRIX(4)(3) & KEY_MATRIX(5)(2) & KEY_MATRIX(5)(3) & KEY_MATRIX(5)(0) & KEY_MATRIX(4)(1) & KEY_MATRIX(5)(4) & KEY_MATRIX(5)(5); -- 4 + when "0100" => + KEY_DATA <= KEY_MATRIX(1)(3) & KEY_MATRIX(3)(0) & KEY_MATRIX(2)(0) & KEY_MATRIX(2)(3) & KEY_MATRIX(2)(4) & KEY_MATRIX(3)(2) & KEY_MATRIX(3)(3) & KEY_MATRIX(4)(2); -- 5 + when "0101" => + KEY_DATA <= KEY_MATRIX(1)(6) & KEY_MATRIX(1)(7) & KEY_MATRIX(2)(6) & KEY_MATRIX(2)(7) & KEY_MATRIX(3)(6) & KEY_MATRIX(3)(7) & KEY_MATRIX(4)(6) & KEY_MATRIX(4)(7); -- 6 + when "0110" => + KEY_DATA <= KEY_MATRIX(7)(6) & KEY_MATRIX(6)(7) & KEY_MATRIX(6)(6) & KEY_MATRIX(4)(0) & KEY_MATRIX(5)(7) & KEY_MATRIX(5)(6) & KEY_MATRIX(5)(1) & KEY_MATRIX(6)(0); -- 7 + when "0111" => + KEY_DATA <= KEY_MATRIX(8)(6) & KEY_MATRIX(9)(6) & KEY_MATRIX(8)(7) & KEY_MATRIX(8)(3) & KEY_MATRIX(9)(4) & KEY_MATRIX(8)(4) & KEY_MATRIX(7)(0) & KEY_MATRIX(6)(1); -- 8 + when "1000" => + KEY_DATA <= KEY_MATRIX(7)(7) & KEY_MATRIX(1)(2) & '1' & '1' & '1' & '1' & '1' & KEY_MATRIX(0)(0); -- 9 + when "1001" => + KEY_DATA <= KEY_MATRIX(8)(2) & KEY_MATRIX(8)(0) & KEY_MATRIX(8)(1) & KEY_MATRIX(9)(0) & KEY_MATRIX(9)(2) & '1' & '1' & '1' ; -- 10 + when others => + KEY_DATA <= "11111111"; + end case; + end if; + end if; + + -- When the Z80_MREQn goes inactive, the keyboard read has completed so clear the substitute flag which in turn allows normal bus operations. + -- + if(KEY_SUBSTITUTE = '1' and Z80_MREQn = '1') then + KEY_SUBSTITUTE <= '0'; + end if; end if; + else + -- Standard mode we dont use the MB logic so set to default. + MB_BUSRQn <= '1'; + MB_STATE <= 0; end if; - else - -- Standard mode we dont use the MB logic so set to default. - MB_BUSRQn <= '1'; - MB_STATE <= 0; end if; - end if; - end process; + end process; + else generate + KEY_SUBSTITUTE <= '0'; + MB_BUSRQn <= '1'; + MB_MREQn <= '1'; + MB_WRITE_STROBE <= '0'; + MB_READ_KEYS <= '0'; + MB_WAITn <= '1'; + MB_ADDR <= (others => '0'); + KEY_DATA <= (others => '0'); + end generate; -- Secondary clock source. If the K64F processor is installed, then use its clock output as the secondary clock as it is more finely programmable. If the K64F -- is not available, use the onboard oscillator. -- CTLCLKSRC: if USE_K64F_CTL_CLOCK = 1 generate - CTLCLKi <= CTLCLK; + CTLCLKi <= CTLCLK; else generate process(Z80_RESETn, CTLCLK) variable FREQDIVCTR : unsigned(3 downto 0); begin if Z80_RESETn = '0' then FREQDIVCTR := (others => '0'); - CTLCLKi <= '0'; + CTLCLKi <= '0'; elsif CTLCLK'event and CTLCLK = '1' then @@ -585,27 +617,27 @@ begin -- high until the falling edge of the clock being switched into. FFCLK1: process( SYSCLK, Z80_RESETn ) begin if Z80_RESETn = '0' then - SYSCLK_Q <= '0'; + SYSCLK_Q <= '0'; -- If the system clock goes active high, process the inputs and set the D-type output. elsif( rising_edge(SYSCLK) ) then if ((DISABLE_BUSn = '1' or MB_BUSRQn = '0' or SCK_CTLSELn = '1') and CTLCLK_Q = '1') then - SYSCLK_Q <= '0'; + SYSCLK_Q <= '0'; else - SYSCLK_Q <= '1'; + SYSCLK_Q <= '1'; end if; end if; end process; FFCLK2: process( CTLCLKi, Z80_RESETn ) begin if Z80_RESETn = '0' then - CTLCLK_Q <= '1'; + CTLCLK_Q <= '1'; -- If the control clock goes active high, process the inputs and set the D-type output. elsif( rising_edge(CTLCLKi) ) then if ((DISABLE_BUSn = '0' and SCK_CTLSELn = '0') and SYSCLK_Q = '1') then - CTLCLK_Q <= '0'; + CTLCLK_Q <= '0'; else - CTLCLK_Q <= '1'; + CTLCLK_Q <= '1'; end if; end if; end process; @@ -629,43 +661,60 @@ begin -- A Video Module signal serializer. Signals required by the Video Module but not accessible physically (without hardware hacks) are captured and serialised as a set of x 4 blocks, clocked by the video module, -- Reset synchronises the Video Module CPLD with the tranZPUter CPLD and the signals are sent during valid mainboard accesses. -- - SIGNALSERIALIZER: process(INCLK, Z80_RESETn) - variable XMIT_CYCLE : integer range 0 to 1; - begin - if Z80_RESETn = '0' then - XMIT_CYCLE := 0; - VIDEOMODULE_PRESENT <= '0'; + MZ80ASERIALISER: if CPLD_HOST_HW = MODE_MZ80A generate + SIGNALSERIALIZER: process(INCLK, Z80_RESETn) + variable XMIT_CYCLE : integer range 0 to 1; + begin + if Z80_RESETn = '0' then + XMIT_CYCLE := 0; + VIDEOMODULE_PRESENT <= '0'; - elsif (INCLK='1' and INCLK'event) then + elsif (INCLK='1' and INCLK'event) then - -- Tight loop, sending current signal status on each clock. There are 16 signals to send and 4 data lines, so we need 4 cycles per data set. - case XMIT_CYCLE is - when 0 => - -- If we are accessing the mainboard then send across a valid signal set else mark it as invalid. - -- - if SYSCLK_Q = '0' then - OUTDATA(3 downto 0) <= Z80_ADDR(14 downto 11); - OUTBUF <= VZ80_IORQn & CS_VIDEO_WRn & CS_VIDEO_RDn & Z80_ADDR(15); - else - OUTDATA(3 downto 0) <= (others => '0'); - OUTBUF <= (others => '0'); - end if; - XMIT_CYCLE := 1; + -- Tight loop, sending current signal status on each clock. There are 16 signals to send and 4 data lines, so we need 4 cycles per data set. + case XMIT_CYCLE is + when 0 => + -- If we are accessing the mainboard then send across a valid signal set else mark it as invalid. + -- + if SYSCLK_Q = '0' then + OUTDATA(3 downto 0) <= Z80_ADDR(14 downto 11); + OUTBUF <= VZ80_IORQn & CS_VIDEO_WRn & CS_VIDEO_RDn & Z80_ADDR(15); + else + OUTDATA(3 downto 0) <= (others => '0'); + OUTBUF <= (others => '0'); + end if; + XMIT_CYCLE := 1; - when 1 => - -- Double check, if we started with a valid mainboard cycle but the clock switched, or we started with an invalid mainboard - -- cycle and the clock switched to mainboard, then invalidate this cycle, otherwise send the final signals as captured at the - -- start of the cycle. - if SYSCLK_Q = '0' and OUTBUF(3 downto 1) /= "000" then - OUTDATA(3 downto 0) <= OUTBUF(3 downto 0); - else - OUTDATA(3 downto 0) <= (others => '0'); - end if; - VIDEOMODULE_PRESENT <= '1'; - XMIT_CYCLE := 0; - end case; - end if; - end process; + when 1 => + -- Double check, if we started with a valid mainboard cycle but the clock switched, or we started with an invalid mainboard + -- cycle and the clock switched to mainboard, then invalidate this cycle, otherwise send the final signals as captured at the + -- start of the cycle. + if SYSCLK_Q = '0' and OUTBUF(3 downto 1) /= "000" then + OUTDATA(3 downto 0) <= OUTBUF(3 downto 0); + else + OUTDATA(3 downto 0) <= (others => '0'); + end if; + VIDEOMODULE_PRESENT <= '1'; + XMIT_CYCLE := 0; + end case; + end if; + end process; + + -- Read from memory and IO devices within the FPGA. + CS_VIDEO_RDn <= '0' when (CS_VIDEO_MEMn = '0' or CS_VIDEO_IOn = '0') and Z80_RDn = '0' + else '1'; + + -- Write to memory and IO devices within the FPGA. Duplicate the transaction to the FPGA for CPLD register writes 0x60:0x6F so that the FPGA can register current settings. + CS_VIDEO_WRn <= '0' when (CS_VIDEO_MEMn = '0' or CS_VIDEO_IOn = '0' or CS_IO_EXXn = '0' or CS_IO_6XXn = '0') and Z80_WRn = '0' + else '1'; + + -- Pass through the addres and control signals to the FPGA. + VZ80_IORQn <= '0' when Z80_IORQn = '0' and (Z80_RDn = '0' or Z80_WRn = '0') + else '1'; + else generate + VIDEOMODULE_PRESENT <= '0'; + OUTDATA <= (others => '0'); + end generate; -- Control Registers - This mirrors the Video Module control registers as we need to know when video memory is to be mapped into main memory. -- @@ -677,9 +726,17 @@ begin begin -- Ensure default values at reset. if Z80_RESETn = '0' then - MODE_VIDEO_MZ80A <= '1'; + if CPLD_HOST_HW = MODE_MZ80A then + MODE_VIDEO_MZ80A <= '1'; + else + MODE_VIDEO_MZ80A <= '0'; + end if; MODE_VIDEO_MZ700 <= '0'; - MODE_VIDEO_MZ800 <= '0'; + if CPLD_HOST_HW = MODE_MZ800 then + MODE_VIDEO_MZ800 <= '1'; + else + MODE_VIDEO_MZ800 <= '0'; + end if; MODE_VIDEO_MZ80B <= '0'; MODE_VIDEO_MZ80K <= '0'; MODE_VIDEO_MZ80C <= '0'; @@ -725,7 +782,7 @@ begin end case; end if; - -- memory page register. [0] switches in 16Kb page (1 of 3 pages) of graphics ram to C000 - FFFF. Bits [0] = page, 00 = Off, 1 = Enabled. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF. + -- memory page register. [1:0] switches in 16Kb page (1 of 3 pages) of graphics ram to C000 - FFFF. Bits [0] = page, 0 = Off, 1 = Enabled. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF. if CS_FB_PAGEn = '0' and Z80_WRn = '0' then GRAM_PAGE_ENABLE <= Z80_DATA(0); end if; @@ -771,6 +828,9 @@ begin -- 12 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6. -- 13 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible. -- 14 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible. + -- 21 - Access the FPGA memory by passing through the full 24bit Z80 address, typically from the K64F. + -- 22 - Access to the host mainboard 64K address space only. + -- 23 - Access all memory and IO on the tranZPUter board with the K64F addressing the full 512K RAM. -- 24 - All memory and IO are on the tranZPUter board, 64K block 0 selected. -- 25 - All memory and IO are on the tranZPUter board, 64K block 1 selected. -- 26 - All memory and IO are on the tranZPUter board, 64K block 2 selected. @@ -779,6 +839,7 @@ begin -- 29 - All memory and IO are on the tranZPUter board, 64K block 5 selected. -- 30 - All memory and IO are on the tranZPUter board, 64K block 6 selected. -- 31 - All memory and IO are on the tranZPUter board, 64K block 7 selected. + -- MEMORYMGMT: process(Z80_ADDR, Z80_WRn, Z80_RDn, Z80_IORQn, Z80_MREQn, Z80_M1n, MEM_MODE_LATCH, SYS_BUSACKni, CS_VIDEOn, CS_VIDEO_IOn, CS_IO_DXXn, CS_IO_EXXn, CS_IO_FXXn, CS_CPLD_CFGn, CS_CPLD_INFOn, MODE_CPLD_MB_VIDEOn) begin @@ -789,7 +850,8 @@ begin -- Set 0 - default, no tranZPUter RAM access so hold the DISABLE_BUS signal inactive to ensure the CPU has continuous access to the -- mainboard resources, especially for Refresh of DRAM. when TZMM_ORIG => - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '1'; RAM_WEni <= '1'; RAM_OEni <= '1'; @@ -797,7 +859,6 @@ begin if CS_VIDEOn = '0' then CS_VIDEO_MEMn <= Z80_MREQn; DISABLE_BUSn <= '1'; - else DISABLE_BUSn <= '1'; end if; @@ -806,7 +867,8 @@ begin when TZMM_BOOT => RAM_CSni <= '0'; CS_VIDEO_MEMn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; RAM_WEni <= '1'; @@ -834,7 +896,8 @@ begin when TZMM_TZFS => RAM_CSni <= '0'; CS_VIDEO_MEMn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; @@ -865,14 +928,16 @@ begin if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; CS_VIDEO_MEMn <= Z80_MREQn; elsif(((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000") or (unsigned(Z80_ADDR(15 downto 0)) >= X"E800" and unsigned(Z80_ADDR(15 downto 0)) < X"F000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; if unsigned(Z80_ADDR(15 downto 0)) = X"E800" then RAM_WEni <= '1'; @@ -882,13 +947,15 @@ begin elsif (unsigned(Z80_ADDR(15 downto 0)) >= X"F000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF" and not std_match(Z80_ADDR(15 downto 1), "11110-111111111")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "001" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000001"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -901,16 +968,16 @@ begin if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; CS_VIDEO_MEMn <= Z80_MREQn; elsif( ((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000") or (unsigned(Z80_ADDR(15 downto 0)) >= X"E800" and unsigned(Z80_ADDR(15 downto 0)) < X"F000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); - RAM_OEni <= Z80_RDn; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; if unsigned(Z80_ADDR(15 downto 0)) = X"E800" then RAM_WEni <= '1'; @@ -920,13 +987,15 @@ begin elsif((unsigned(Z80_ADDR(15 downto 0)) >= X"F000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "010" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000010"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -939,14 +1008,16 @@ begin if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; CS_VIDEO_MEMn <= Z80_MREQn; elsif( ((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000") or (unsigned(Z80_ADDR(15 downto 0)) >= X"E800" and unsigned(Z80_ADDR(15 downto 0)) < X"F000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; if unsigned(Z80_ADDR(15 downto 0)) = X"E800" then RAM_WEni <= '1'; @@ -956,13 +1027,15 @@ begin elsif((unsigned(Z80_ADDR(15 downto 0)) >= X"F000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "011" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000011"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -975,13 +1048,15 @@ begin if (unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF" and not std_match(Z80_ADDR(15 downto 1), "11110-111111111")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "100" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -995,36 +1070,41 @@ begin if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; CS_VIDEO_MEMn <= Z80_MREQn; elsif ((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"0100") or (unsigned(Z80_ADDR(15 downto 0)) >= X"F000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF" and not std_match(Z80_ADDR(15 downto 1), "11110-111111111"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "100" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000100"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif(((unsigned(Z80_ADDR(15 downto 0)) >= X"0100" and unsigned(Z80_ADDR(15 downto 0)) < X"D000") or (unsigned(Z80_ADDR(15 downto 0)) >= X"E800" and unsigned(Z80_ADDR(15 downto 0)) < X"F000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "101" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000101"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; -- Set 8 - Monitor ROM 0000-0FFF on mainboard, Main DRAM 0x1000-0xD000 is in tranZPUter memory. -- NB: Main DRAM will not be refreshed so cannot be used to store data in this mode. - when TZMM_ORIGMON => + when TZMM_COMPAT => RAM_CSni <= '0'; CS_VIDEO_MEMn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; @@ -1050,26 +1130,30 @@ begin if CS_VIDEOn = '0' then DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; CS_VIDEO_MEMn <= Z80_MREQn; elsif(((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"1000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "110" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000110"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif((unsigned(Z80_ADDR(15 downto 0)) >= X"1000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -1081,25 +1165,29 @@ begin if(((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"1000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif((unsigned(Z80_ADDR(15 downto 0)) >= X"1000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif(((unsigned(Z80_ADDR(15 downto 0)) >= X"D000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "110" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000110"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -1111,25 +1199,29 @@ begin if(((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"1000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "110" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000110"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif((unsigned(Z80_ADDR(15 downto 0)) >= X"1000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif(((unsigned(Z80_ADDR(15 downto 0)) >= X"D000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "110" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000110"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -1141,25 +1233,29 @@ begin if(((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"1000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif((unsigned(Z80_ADDR(15 downto 0)) >= X"1000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif(((unsigned(Z80_ADDR(15 downto 0)) >= X"D000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF"))) then DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; @@ -1171,33 +1267,67 @@ begin if(((unsigned(Z80_ADDR(15 downto 0)) >= X"0000" and unsigned(Z80_ADDR(15 downto 0)) < X"1000"))) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "110" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000110"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif((unsigned(Z80_ADDR(15 downto 0)) >= X"1000" and unsigned(Z80_ADDR(15 downto 0)) < X"D000")) then DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; elsif(((unsigned(Z80_ADDR(15 downto 0)) >= X"D000" and unsigned(Z80_ADDR(15 downto 0)) <= X"FFFF"))) then DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; else DISABLE_BUSn <= '1'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_WEni <= '1'; RAM_OEni <= '1'; end if; + -- Set 21 - Access the FPGA memory by passing through the full 24bit Z80 address, typically from the K64F. + when TZMM_FPGA => + DISABLE_BUSn <= '0'; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); + RAM_CSni <= '1'; + RAM_WEni <= '1'; + RAM_OEni <= '1'; + CS_VIDEO_MEMn <= '1'; + + -- Set 22 - Access to the host mainboard 64K address space. + when TZMM_TZPUM => + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); + RAM_CSni <= '1'; + RAM_WEni <= '1'; + RAM_OEni <= '1'; + CS_VIDEO_MEMn <= '1'; + DISABLE_BUSn <= '1'; + + -- Set 23 - Access all memory and IO on the tranZPUter board with the K64F addressing the full 512K RAM. + when TZMM_TZPU => + DISABLE_BUSn <= '0'; + Z80_HI_ADDRi <= "00000000"; -- Hi bits directly driven by external source, + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); + RAM_CSni <= '0'; + RAM_OEni <= Z80_RDn; + RAM_WEni <= Z80_WRn; + CS_VIDEO_MEMn <= '1'; + -- Set 24 - All memory and IO are on the tranZPUter board, 64K block 0 selected. when TZMM_TZPU0 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1206,7 +1336,8 @@ begin -- Set 25 - All memory and IO are on the tranZPUter board, 64K block 1 selected. when TZMM_TZPU1 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "001" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000001"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1215,7 +1346,8 @@ begin -- Set 26 - All memory and IO are on the tranZPUter board, 64K block 2 selected. when TZMM_TZPU2 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "010" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000010"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1224,7 +1356,8 @@ begin -- Set 27 - All memory and IO are on the tranZPUter board, 64K block 3 selected. when TZMM_TZPU3 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "011" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000011"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1233,7 +1366,8 @@ begin -- Set 28 - All memory and IO are on the tranZPUter board, 64K block 4 selected. when TZMM_TZPU4 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "100" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000100"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1242,7 +1376,8 @@ begin -- Set 29 - All memory and IO are on the tranZPUter board, 64K block 5 selected. when TZMM_TZPU5 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "101" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000101"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1251,7 +1386,8 @@ begin -- Set 30 - All memory and IO are on the tranZPUter board, 64K block 6 selected. when TZMM_TZPU6 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "110" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000110"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1260,7 +1396,8 @@ begin -- Set 31 - All memory and IO are on the tranZPUter board, 64K block 7 selected. when TZMM_TZPU7 => DISABLE_BUSn <= '0'; - Z80_HI_ADDR(18 downto 12) <= "111" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000111"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '0'; RAM_OEni <= Z80_RDn; RAM_WEni <= Z80_WRn; @@ -1268,7 +1405,8 @@ begin -- Uncoded modes default to the original machine settings. when others => - Z80_HI_ADDR(18 downto 12) <= "000" & Z80_ADDR(15 downto 12); + Z80_HI_ADDRi <= "00000000"; + Z80_RA_ADDRi <= Z80_ADDR(15 downto 12); RAM_CSni <= '1'; RAM_WEni <= '1'; RAM_OEni <= '1'; @@ -1309,13 +1447,29 @@ begin end if; end process; - -- Latch output so the K64F can determine current status. - Z80_MEM <= MEM_MODE_LATCH(4 downto 0); + -- A process to bring the external K64F control signals into this domain. The K64F can request the bus asynchronously so it is important the system state is known before + -- passing the request onto the internal processes. + -- + SIGNALSYNC: process( Z80_CLKi, Z80_RESETn, CTL_BUSRQn ) + begin + + if(Z80_RESETn = '0') then + CTL_BUSRQni <= '1'; + + elsif rising_edge(Z80_CLKi) then + -- When a Bus request comes in, ensure that the state is idle before passing it on as this signal is used to enable/disable or mux control other signals. + if CTL_BUSRQn = '0' then + CTL_BUSRQni <= '0'; + end if; + if CTL_BUSRQn = '1' then + CTL_BUSRQni <= '1'; + end if; + end if; + end process; -- Clock frequency switching. Depending on the state of the flip flops either the system (mainboard) clocks is selected (default and selected when accessing -- the mainboard) and the programmable frequency generated by the K64F timers. Z80_CLKi <= (SYSCLK or SYSCLK_Q) and (CTLCLKi or CTLCLK_Q); - CTL_CLKSLCT <= SYSCLK_Q; Z80_CLK <= Z80_CLKi; -- Wait states, added by the video circuitry or the K64F. @@ -1330,18 +1484,35 @@ begin CTL_HALTn <= Z80_HALTn when Z80_BUSACKn = '1' else 'Z'; - -- Bus control logic. - SYS_BUSACKni <= '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' - else - '0' when DISABLE_BUSn = '0' or (KEY_SUBSTITUTE = '1' and Z80_MREQn = '0') or (Z80_BUSACKn = '0' and CTL_BUSACKn = '0') + -- Bus control logic, SYS_BUSACKni directly controls the mainboard tri-state buffers, enabling will disable the mainboard. + SYS_BUSACKni <= '0' when DISABLE_BUSn = '0' or (KEY_SUBSTITUTE = '1' and Z80_MREQn = '0') or (Z80_BUSACKn = '0' and CTL_MBSEL = '0') else '1'; SYS_BUSACKn <= SYS_BUSACKni; - Z80_BUSRQn <= '0' when SYS_BUSRQn = '0' or CTL_BUSRQn = '0' or MB_BUSRQn = '0' + Z80_BUSRQn <= '0' when SYS_BUSRQn = '0' or CTL_BUSRQni = '0' or MB_BUSRQn = '0' else '1'; + -- Acknowlegde to the K64F it has bus control. + CTL_BUSACKni <= '0' when CTL_BUSRQni = '0' and Z80_BUSACKn = '0' + else '1'; + CTL_BUSACKn <= CTL_BUSACKni; + -- Register read values. CLK_STATUS_DATA <= "0000000" & SYSCLK_Q; MEM_MODE_DATA <= "000" & MEM_MODE_LATCH(4 downto 0); + + -- CPLD information register. + -- [2:0] - R/O - Physical hardware. + -- 000 = MZ-80K + -- 001 = MZ-80C + -- 010 = MZ-1200 + -- 011 = MZ-80A + -- 100 = MZ-700 + -- 101 = MZ-800 + -- 110 = MZ-80B + -- 111 = MZ-2000 + -- [3] R/O - FPGA Video Capable, 1 = FPGA Video capable, 0 = no FPGA. + -- [7:5] R/O - CPLD Version number, 0..7 + -- CPLD_INFO_DATA <= std_logic_vector(to_unsigned(CPLD_VERSION, 3)) & '0' & CPLD_HAS_FPGA_VIDEO & std_logic_vector(to_unsigned(CPLD_HOST_HW, 3)); -- @@ -1357,13 +1528,17 @@ begin else KEY_DATA when MB_BUSRQn = '1' and Z80_BUSACKn = '1' and KEY_SUBSTITUTE = '1' and Z80_MREQn = '0' -- Read mapped keyboard data. else - (others => 'Z') when Z80_BUSACKn = '0' and CTL_BUSACKn = '0' -- Tristate bus when Z80 tristated and the K64F is requesting all devices to tristate. + (others => 'Z') when Z80_BUSACKn = '0' and CTL_BUSACKni = '0' -- Tristate bus when Z80 tristated and the K64F is requesting all devices to tristate. else (others => 'Z'); -- Default is to tristate the CPLD data bus output when not being used. -- -- Address Bus Multiplexing. -- + -- + Z80_HI_ADDR <= Z80_HI_ADDRi when CTL_BUSACKni = '1' -- New addition, pass through the upper address bits directly. K64F directly drives A16-A23 to RAM and into CPLD. + else (others => 'Z'); + Z80_RA_ADDR <= Z80_RA_ADDRi; Z80_ADDR <= MB_ADDR when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else (others => 'Z'); @@ -1450,13 +1625,6 @@ begin '0' when MODE_CPLD_MB_VIDEOn = '1' and GRAM_PAGE_ENABLE = '0' and MODE_VIDEO_MZ80B = '1' and MZ80B_VRAM_LO_ADDR = '1' and unsigned(Z80_ADDR(15 downto 0)) >= X"5000" and unsigned(Z80_ADDR(15 downto 0)) <= X"7FFF" else '1'; - -- Read from memory and IO devices within the FPGA. - CS_VIDEO_RDn <= '0' when (CS_VIDEO_MEMn = '0' or CS_VIDEO_IOn = '0') and Z80_RDn = '0' - else '1'; - - -- Write to memory and IO devices within the FPGA. Duplicate the transaction to the FPGA for CPLD register writes 0x60:0x6F so that the FPGA can register current settings. - CS_VIDEO_WRn <= '0' when (CS_VIDEO_MEMn = '0' or CS_VIDEO_IOn = '0' or CS_IO_EXXn = '0' or CS_IO_6XXn = '0') and Z80_WRn = '0' - else '1'; -- Set the mainboard video state, 0 = enabled, 1 = disabled. The flag is set if the CPLD Config register Bit 3 is set or if the Serializer @@ -1481,31 +1649,28 @@ begin MODE_CPLD_MZ2000 <= '1' when to_integer(unsigned(CPLD_CFG_DATA(2 downto 0))) = MODE_MZ2000 else '0'; - -- Pass through the addres and control signals to the FPGA. - VZ80_IORQn <= '0' when Z80_IORQn = '0' and (Z80_RDn = '0' or Z80_WRn = '0') - else '1'; -- Mainboard WAIT State Generator S-R latch 4. -- NB: V2.1 design doesnt need the wait state generator as the mapping is done in hardware. -- - --MBWAITGEN: process(SYSCLK, Z80_ADDR, Z80_M1n, CTL_BUSRQn, MEM_MODE_LATCH, Z80_IORQn) + --MBWAITGEN: process(SYSCLK, Z80_ADDR, Z80_M1n, CTL_BUSRQni, MEM_MODE_LATCH, Z80_IORQn) -- variable tmp : std_logic; -- variable iowait : std_logic; --begin -- -- -- IO Wait select active when an IO operation is made in range 0xE0-0xFF. - -- if (Z80_ADDR(7 downto 5) = "111" and Z80_M1n = '1' and CTL_BUSRQn = '1' and MEM_MODE_LATCH(5) = '1' and Z80_IORQn = '0') then + -- if (Z80_ADDR(7 downto 5) = "111" and Z80_M1n = '1' and CTL_BUSRQni = '1' and MEM_MODE_LATCH(5) = '1' and Z80_IORQn = '0') then -- iowait := '0'; -- else -- iowait := '1'; -- end if; -- -- if(SYSCLK='1' and SYSCLK'event) then - -- if((CTL_BUSRQn = '1' and Z80_RESETn = '1') and iowait = '1') then + -- if((CTL_BUSRQni = '1' and Z80_RESETn = '1') and iowait = '1') then -- tmp := tmp; - -- elsif((CTL_BUSRQn = '0' or Z80_RESETn = '0') and iowait = '0') then + -- elsif((CTL_BUSRQni = '0' or Z80_RESETn = '0') and iowait = '0') then -- tmp := 'Z'; - -- elsif((CTL_BUSRQn = '0' or Z80_RESETn = '0') and iowait = '1') then + -- elsif((CTL_BUSRQni = '0' or Z80_RESETn = '0') and iowait = '1') then -- tmp := '1'; -- else -- tmp := '0'; diff --git a/CPLD/SW/tranZPUterSW_Toplevel.vhd b/CPLD/SW/tranZPUterSW_Toplevel.vhd index 02d3694..c7b57d0 100644 --- a/CPLD/SW/tranZPUterSW_Toplevel.vhd +++ b/CPLD/SW/tranZPUterSW_Toplevel.vhd @@ -11,6 +11,7 @@ -- Copyright: (c) 2018-20 Philip Smart -- -- History: June 2020 - Initial creation. +-- Z80_HI_ADDR, - Z80_ADDR => Z80_ADDR, - Z80_DATA => Z80_DATA, + Z80_HI_ADDR => Z80_HI_ADDR, + Z80_RA_ADDR => Z80_RA_ADDR, + Z80_ADDR => Z80_ADDR, + Z80_DATA => Z80_DATA, -- Z80 Control signals. - Z80_BUSRQn => Z80_BUSRQn, - Z80_BUSACKn => Z80_BUSACKn, - Z80_INTn => Z80_INTn, - Z80_IORQn => Z80_IORQn, - Z80_MREQn => Z80_MREQn, - Z80_NMIn => Z80_NMIn, - Z80_RDn => Z80_RDn, - Z80_WRn => Z80_WRn, - Z80_RESETn => Z80_RESETn, - Z80_HALTn => Z80_HALTn, - Z80_WAITn => Z80_WAITn, - Z80_M1n => Z80_M1n, - Z80_RFSHn => Z80_RFSHn, - Z80_CLK => Z80_CLK, + Z80_BUSRQn => Z80_BUSRQn, + Z80_BUSACKn => Z80_BUSACKn, + Z80_INTn => Z80_INTn, + Z80_IORQn => Z80_IORQn, + Z80_MREQn => Z80_MREQn, + Z80_NMIn => Z80_NMIn, + Z80_RDn => Z80_RDn, + Z80_WRn => Z80_WRn, + Z80_RESETn => Z80_RESETn, + Z80_HALTn => Z80_HALTn, + Z80_WAITn => Z80_WAITn, + Z80_M1n => Z80_M1n, + Z80_RFSHn => Z80_RFSHn, + Z80_CLK => Z80_CLK, -- K64F control signals. - CTL_BUSACKn => CTL_BUSACKn, - CTL_BUSRQn => CTL_BUSRQn, - CTL_HALTn => CTL_HALTn, - CTL_M1n => CTL_M1n, - CTL_RFSHn => CTL_RFSHn, - CTL_WAITn => CTL_WAITn, - SVCREQn => SVCREQn, - Z80_MEM => Z80_MEM, + CTL_MBSEL => CTL_MBSEL, + CTL_BUSRQn => CTL_BUSRQn, + CTL_BUSACKn => CTL_BUSACKn, + CTL_HALTn => CTL_HALTn, + CTL_M1n => CTL_M1n, + CTL_RFSHn => CTL_RFSHn, + CTL_WAITn => CTL_WAITn, + SVCREQn => SVCREQn, -- Mainboard signals which are blended with K64F signals to activate corresponding Z80 functionality. - SYS_BUSACKn => SYS_BUSACKn, - SYS_BUSRQn => SYS_BUSRQn, - SYS_WAITn => SYS_WAITn, - SYS_WRn => SYS_WRn, - SYS_RDn => SYS_RDn, + SYS_BUSACKn => SYS_BUSACKn, + SYS_BUSRQn => SYS_BUSRQn, + SYS_WAITn => SYS_WAITn, + SYS_WRn => SYS_WRn, + SYS_RDn => SYS_RDn, -- RAM control. - RAM_CSn => RAM_CSn, - RAM_OEn => RAM_OEn, - RAM_WEn => RAM_WEn, + RAM_CSn => RAM_CSn, + RAM_OEn => RAM_OEn, + RAM_WEn => RAM_WEn, -- Graphics Board I/O and Memory Select. - INCLK => INCLK, - OUTDATA => OUTDATA, + INCLK => INCLK, + OUTDATA => OUTDATA, -- Clocks, system and K64F generated. - SYSCLK => SYSCLK, - CTLCLK => CTLCLK, - CTL_CLKSLCT => CTL_CLKSLCT + SYSCLK => SYSCLK, + CTLCLK => CTLCLK ); end architecture; diff --git a/CPLD/SW/tranZPUterSW_pkg.vhd b/CPLD/SW/tranZPUterSW_pkg.vhd index 976ba5e..6d3e25d 100644 --- a/CPLD/SW/tranZPUterSW_pkg.vhd +++ b/CPLD/SW/tranZPUterSW_pkg.vhd @@ -5,12 +5,13 @@ -- Author(s): Philip Smart -- Description: tranZPUter SW CPLD configuration file. -- --- This module contains parameters for the CPLD in v2.1 of the tranZPUterSW project. +-- This module contains parameters for the CPLD in v2.1 - v2.2 of the tranZPUterSW project. -- -- Credits: -- Copyright: (c) 2018-20 Philip Smart -- -- History: June 2020 - Initial creation. +-- Mar 2021 - Updated to enable better compatibility with the Sharp MZ-800. -- --------------------------------------------------------------------------------------------------------- -- This source file is free software: you can redistribute it and-or modify @@ -68,12 +69,15 @@ package tranZPUterSW_pkg is constant TZMM_CPM : integer := 06; -- CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard. constant TZMM_CPM2 : integer := 07; -- CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected. -- Special case for 0000:003F (interrupt vectors) which resides in block 4, F3FE:F3FF & F7FE:F7FF (floppy disk paging vectors) which resides on the mainboard. - constant TZMM_ORIGMON : integer := 08; -- Original monitor mode, monitor ROM on mainboard, RAM on tranZPUter in Block 0 1000-CFFF. + constant TZMM_COMPAT : integer := 08; -- Compatibility monitor mode, monitor ROM on mainboard, RAM on tranZPUter in Block 0 1000-CFFF. constant TZMM_MZ700_0 : integer := 10; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard. constant TZMM_MZ700_1 : integer := 11; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6. constant TZMM_MZ700_2 : integer := 12; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6. constant TZMM_MZ700_3 : integer := 13; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible. constant TZMM_MZ700_4 : integer := 14; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible. + constant TZMM_FPGA : integer := 21; -- Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked. + constant TZMM_TZPUM : integer := 22; -- Everything in on mainboard, no access to tranZPUter memory. + constant TZMM_TZPU : integer := 23; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected. constant TZMM_TZPU0 : integer := 24; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected. constant TZMM_TZPU1 : integer := 25; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected. constant TZMM_TZPU2 : integer := 26; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected. @@ -83,11 +87,14 @@ package tranZPUterSW_pkg is constant TZMM_TZPU6 : integer := 30; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected. constant TZMM_TZPU7 : integer := 31; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected. + + ------------------------------------------------------------ -- Configurable parameters. ------------------------------------------------------------ -- Target hardware. - constant CPLD_HOST_HW : integer := MODE_MZ80A; + constant CPLD_HOST_HW : integer := MODE_MZ800; + --constant CPLD_HOST_HW : integer := MODE_MZ80A; -- Target video hardware. constant CPLD_HAS_FPGA_VIDEO : std_logic := '1'; @@ -95,7 +102,7 @@ package tranZPUterSW_pkg is -- Version of hdl. constant CPLD_VERSION : integer := 1; - -- Clock source for the secondary clock. If a K64F is installed the enable it otherwise use the onboard oscillator. + -- Clock source for the secondary clock. If a K64F is installed then enable it otherwise use the onboard oscillator. -- constant USE_K64F_CTL_CLOCK : integer := 1; @@ -111,6 +118,17 @@ package tranZPUterSW_pkg is -- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns. function clockTicks(period : in integer; clock : in integer) return integer; + -- Function to reverse the order of the bits in a standard logic vector. + -- ie. 1010 becomes 0101 + function reverse_vector(slv:std_logic_vector) return std_logic_vector; + + -- Function to convert an integer (0 or 1) into std_logic. + -- + function to_std_logic(i : in integer) return std_logic; + + -- Function to return the value of a bit as an integer for array indexing etc. + function bit_to_integer( s : std_logic ) return natural; + ------------------------------------------------------------ -- Records ------------------------------------------------------------ @@ -167,4 +185,30 @@ package body tranZPUterSW_pkg is end if; end function; + function reverse_vector(slv:std_logic_vector) return std_logic_vector is + variable target : std_logic_vector(slv'high downto slv'low); + begin + for idx in slv'high downto slv'low loop + target(idx) := slv(slv'low + (slv'high-idx)); + end loop; + return target; + end reverse_vector; + + function to_std_logic(i : in integer) return std_logic is + begin + if i = 0 then + return '0'; + end if; + return '1'; + end function; + + -- Function to return the value of a bit as an integer for array indexing etc. + function bit_to_integer( s : std_logic ) return natural is + begin + if s = '1' then + return 1; + else + return 0; + end if; + end function; end package body; diff --git a/CPLD/SW700/v1.2/tranZPUterSW700.vhd b/CPLD/SW700/v1.2/tranZPUterSW700.vhd index 5b8d9f0..d1a822c 100644 --- a/CPLD/SW700/v1.2/tranZPUterSW700.vhd +++ b/CPLD/SW700/v1.2/tranZPUterSW700.vhd @@ -34,6 +34,9 @@ -- as there are a lot of pin and logic differences. The tranZPUter SW is still -- under development so didnt make sense to share the same files and make -- them conditional. +-- Mar 2021 - Better control of the external Asyn BUSRQ/BUSACK was needed, bringing in +-- the async K64F CTL_BUSRQ into the Z80 clocked domain and adjustment of +-- mux lines. -- --------------------------------------------------------------------------------------------------------- -- This source file is free software: you can redistribute it and-or modify @@ -82,7 +85,7 @@ entity cpld512 is Z80_CLK : out std_logic; -- K64F control signals. - CTL_BUSACKn : in std_logic; + CTL_BUSACKn : out std_logic; CTL_BUSRQn : in std_logic; CTL_HALTn : out std_logic; CTL_M1n : out std_logic; @@ -191,6 +194,8 @@ architecture rtl of cpld512 is -- signal DISABLE_BUSn : std_logic; -- Signal to disable access to the mainboard (= 0) via the SYS_BUSACKn signal which tri-states the mainboard logic. signal SYS_BUSACKni : std_logic := '0'; -- Signal to hold the current state of the SYS_BUSACKn signal used to activate/tri-state the mainboard logic. + signal CTL_BUSACKni : std_logic; -- Buffered BUSACK signal to the K64F to indicate it has control of the bus. + signal CTL_BUSRQni : std_logic; -- -- CPU Frequency select logic based on Flip Flops and gates. signal SCK_CTLSELn : std_logic; @@ -267,6 +272,13 @@ begin -- [4] - R/W - Enable WAIT state during frame display period. 1 = Enable, 0 = Disable (default). The flag enables Z80 WAIT assertion during the frame display period. Most video modes -- use double buffering so this isnt needed, but use of direct writes to the frame buffer in 8 colour mode (ie. 640x200 or 320x200 8 colour) there -- is not enough memory to double buffer so potentially there could be tear or snow, hence this optional wait generator. + --*[6:5] - R/W - Mainboard/CPU clock. + -- 000 = Sharp MZ80A 2MHz System Clock. + -- 001 = Sharp MZ80B 4MHz System Clock. + -- 010 = Sharp MZ700 3.54MHz System Clock. + -- 011 -111 = Reserved, defaults to 2MHz System Clock. + -- [7] - R/W - Preserve configuration over reset (=1) or set to default on reset (=0). + -- * = SW v2.2 MZ-80A version only, not used in other CPLD versions. -- MACHINEMODE: process( Z80_CLKi, Z80_RESETn, CS_CPLD_CFGn, Z80_ADDR, Z80_DATA ) begin @@ -275,7 +287,7 @@ begin MODE_CPLD_SWITCH <= '0'; CPLD_CFG_DATA <= "00000100"; -- Default to Sharp MZ700, mainboard video enabled, wait state off. - elsif(Z80_CLKi'event and Z80_CLKi = '1') then + elsif(rising_edge(Z80_CLKi)) then -- Write to config register. if(CS_CPLD_CFGn = '0' and Z80_WRn = '0') then @@ -293,7 +305,6 @@ begin end if; end process; - -- Memory mode latch. This latch stores the current memory mode (or Bank Paging Scheme) according to the running software. -- MEMORYMODE: process( Z80_CLKi, Z80_RESETn, CS_MEM_CFGn, Z80_IORQn, Z80_WRn, Z80_ADDR, Z80_DATA ) @@ -581,14 +592,14 @@ begin -- is not available, use the onboard oscillator. -- CTLCLKSRC: if USE_K64F_CTL_CLOCK = 1 generate - CTLCLKi <= CTLCLK; + CTLCLKi <= CTLCLK; else generate process(Z80_RESETn, CTLCLK) variable FREQDIVCTR : unsigned(3 downto 0); begin if Z80_RESETn = '0' then FREQDIVCTR := (others => '0'); - CTLCLKi <= '0'; + CTLCLKi <= '0'; elsif CTLCLK'event and CTLCLK = '1' then @@ -607,27 +618,27 @@ begin -- high until the falling edge of the clock being switched into. FFCLK1: process( SYSCLK, Z80_RESETn ) begin if Z80_RESETn = '0' then - SYSCLK_Q <= '0'; + SYSCLK_Q <= '0'; -- If the system clock goes active high, process the inputs and set the D-type output. elsif( rising_edge(SYSCLK) ) then if ((DISABLE_BUSn = '1' or MB_BUSRQn = '0' or SCK_CTLSELn = '1') and CTLCLK_Q = '1') then - SYSCLK_Q <= '0'; + SYSCLK_Q <= '0'; else - SYSCLK_Q <= '1'; + SYSCLK_Q <= '1'; end if; end if; end process; FFCLK2: process( CTLCLKi, Z80_RESETn ) begin if Z80_RESETn = '0' then - CTLCLK_Q <= '1'; + CTLCLK_Q <= '1'; -- If the control clock goes active high, process the inputs and set the D-type output. elsif( rising_edge(CTLCLKi) ) then if ((DISABLE_BUSn = '0' and SCK_CTLSELn = '0') and SYSCLK_Q = '1') then - CTLCLK_Q <= '0'; + CTLCLK_Q <= '0'; else - CTLCLK_Q <= '1'; + CTLCLK_Q <= '1'; end if; end if; end process; @@ -752,6 +763,9 @@ begin -- 12 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6. -- 13 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible. -- 14 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible. + -- *21 - Access the FPGA memory by passing through the full 24bit Z80 address, typically from the K64F. + -- *22 - Access to the host mainboard 64K address space only. + -- *23 - Access all memory and IO on the tranZPUter board with the K64F addressing the full 512K RAM. -- 24 - All memory and IO are on the tranZPUter board, 64K block 0 selected. -- 25 - All memory and IO are on the tranZPUter board, 64K block 1 selected. -- 26 - All memory and IO are on the tranZPUter board, 64K block 2 selected. @@ -760,6 +774,8 @@ begin -- 29 - All memory and IO are on the tranZPUter board, 64K block 5 selected. -- 30 - All memory and IO are on the tranZPUter board, 64K block 6 selected. -- 31 - All memory and IO are on the tranZPUter board, 64K block 7 selected. + -- + -- * = Only on SW-700 v1.3 MEMORYMGMT: process(Z80_ADDR, Z80_WRn, Z80_RDn, Z80_IORQn, Z80_MREQn, Z80_M1n, MEM_MODE_LATCH, SYS_BUSACKni, CS_VIDEOn, CS_VIDEO_IOn, CS_IO_DXXn, CS_IO_EXXn, CS_IO_FXXn, MODE_CPLD_MB_VIDEOn) begin @@ -1175,6 +1191,15 @@ begin RAM_OEni <= '1'; end if; + -- Set 21 - Access the FPGA memory by passing through the full 24bit Z80 address, typically from the K64F. + when TZMM_FPGA => + + -- Set 22 - Access to the host mainboard 64K address space. + when TZMM_TZPUM => + + -- Set 23 - Access all memory and IO on the tranZPUter board with the K64F addressing the full 512K RAM. + when TZMM_TZPU => + -- Set 24 - All memory and IO are on the tranZPUter board, 64K block 0 selected. when TZMM_TZPU0 => DISABLE_BUSn <= '0'; @@ -1289,6 +1314,26 @@ begin end if; end process; + -- A process to bring the external K64F control signals into this domain. The K64F can request the bus asynchronously so it is important the system state is known before + -- passing the request onto the internal processes. + -- + SIGNALSYNC: process( Z80_CLKi, Z80_RESETn, CTL_BUSRQn ) + begin + + if(Z80_RESETn = '0') then + CTL_BUSRQni <= '1'; + + elsif rising_edge(Z80_CLKi) then + -- When a Bus request comes in, ensure that the state is idle before passing it on as this signal is used to enable/disable or mux control other signals. + if CTL_BUSRQn = '0' then + CTL_BUSRQni <= '0'; + end if; + if CTL_BUSRQn = '1' then + CTL_BUSRQni <= '1'; + end if; + end if; + end process; + -- Latch output so the K64F can determine current status. Z80_MEM <= MEM_MODE_LATCH(4 downto 0); @@ -1298,7 +1343,6 @@ begin CTL_CLKSLCT <= SYSCLK_Q; Z80_CLK <= Z80_CLKi; - -- Wait states, added by the mainboard video circuitry, FPGA video circuitry or the K64F. Z80_WAITn <= '0' when SYS_WAITn = '0' or CTL_WAITn = '0' or (VWAITn = '0' and MODE_CPLD_VIDEO_WAIT = '1') or MB_WAITn = '0' else '1'; @@ -1314,12 +1358,17 @@ begin -- Bus control logic. SYS_BUSACKni <= '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else - '0' when DISABLE_BUSn = '0' or (KEY_SUBSTITUTE = '1' and Z80_MREQn = '0') or (Z80_BUSACKn = '0' and CTL_BUSACKn = '0') + '0' when DISABLE_BUSn = '0' or (KEY_SUBSTITUTE = '1' and Z80_MREQn = '0') or (Z80_BUSACKn = '0' and CTL_BUSACKni = '0') else '1'; SYS_BUSACKn <= SYS_BUSACKni; - Z80_BUSRQn <= '0' when SYS_BUSRQn = '0' or CTL_BUSRQn = '0' or MB_BUSRQn = '0' + Z80_BUSRQn <= '0' when SYS_BUSRQn = '0' or CTL_BUSRQni = '0' or MB_BUSRQn = '0' else '1'; + -- Acknowlegde to the K64F it has bus control. + CTL_BUSACKni <= '0' when CTL_BUSRQni = '0' and Z80_BUSACKn = '0' + else '1'; + CTL_BUSACKn <= CTL_BUSACKni; + -- Register read values. CLK_STATUS_DATA <= "0000000" & SYSCLK_Q; MEM_MODE_DATA <= "000" & MEM_MODE_LATCH(4 downto 0); @@ -1364,7 +1413,7 @@ begin else MEM_MODE_DATA when CS_MEM_CFGn = '0' and Z80_RDn = '0' -- Read the memory mode latch. else - (others => 'Z') when Z80_BUSACKn = '0' and CTL_BUSACKn = '0' -- Tristate bus when Z80 tristated and the K64F is requesting all devices to tristate. + (others => 'Z') when Z80_BUSACKn = '0' and CTL_BUSACKni = '0' -- Tristate bus when Z80 tristated and the K64F is requesting all devices to tristate. -- else -- KEY_DATA when MB_BUSRQn = '1' and Z80_BUSACKn = '1' and KEY_SUBSTITUTE = '1' and Z80_MREQn = '0' -- Read mapped keyboard data. -- else @@ -1377,48 +1426,48 @@ begin -- -- Address Bus Multiplexing. -- - Z80_ADDR <= MB_ADDR when Z80_BUSACKn = '0' and MB_BUSRQn = '0' + Z80_ADDR <= MB_ADDR when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else (others => 'Z'); - Z80_WRn <= '0' when MB_MREQn = '0' and Z80_BUSACKn = '0' and (MB_WRITE_STROBE = '1') -- and (write1 or write2...) signals active here + Z80_WRn <= '0' when MB_MREQn = '0' and Z80_BUSACKn = '0' and (MB_WRITE_STROBE = '1') -- and (write1 or write2...) signals active here else - '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' + '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else 'Z'; - Z80_RDn <= '0' when MB_MREQn = '0' and Z80_BUSACKn = '0' and (MB_READ_KEYS = '1') -- and (read1 or read2...) signals active here + Z80_RDn <= '0' when MB_MREQn = '0' and Z80_BUSACKn = '0' and (MB_READ_KEYS = '1') -- and (read1 or read2...) signals active here else - '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' + '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else 'Z'; - Z80_MREQn <= MB_MREQn when Z80_BUSACKn = '0' and MB_BUSRQn = '0' + Z80_MREQn <= MB_MREQn when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else 'Z'; - Z80_INTn <= '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' + Z80_INTn <= '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else 'Z'; - Z80_NMIn <= '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' + Z80_NMIn <= '1' when Z80_BUSACKn = '0' and MB_BUSRQn = '0' else 'Z'; -- The tranZPUter SW board adds upgrades for the Z80 processor and host. These upgrades are controlled through an IO port which -- in v1.0 - v1.1 was either at 0x2-=0x2f, 0x60-0x6f, 0xA0-0xAf, 0xF0-0xFF, the default being 0x60. This logic mimcs the 74HCT138 and -- FlashRAM decoder which produces the I/O port select signals. -- - CS_IO_6XXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "0110" + CS_IO_6XXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "0110" else '1'; - CS_MEM_CFGn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "000" -- IO 60 + CS_MEM_CFGn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "000" -- IO 60 else '1'; - CS_SCK_CTLCLKn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "001" -- IO 62 + CS_SCK_CTLCLKn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "001" -- IO 62 else '1'; - CS_SCK_SYSCLKn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "010" -- IO 64 + CS_SCK_SYSCLKn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "010" -- IO 64 else '1'; - CS_SCK_RDn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "011" -- IO 66 + CS_SCK_RDn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "011" -- IO 66 else '1'; - SVCREQn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "100" -- IO 68 + SVCREQn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 1) = "100" -- IO 68 else '1'; - CS_CPLD_CFGn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 0) = "1110" -- IO 6E + CS_CPLD_CFGn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 0) = "1110" -- IO 6E else '1'; - CS_CPLD_INFOn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 0) = "1111" -- IO 6F + CS_CPLD_INFOn <= '0' when CS_IO_6XXn = '0' and Z80_ADDR(3 downto 0) = "1111" -- IO 6F else '1'; -- Assign the RAM select signals to their external pins. @@ -1429,21 +1478,21 @@ begin else '1'; -- I/O Control signals to read and update the current video parameters, mainly used for setting FPGA access. - CS_IO_DXXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "1101" + CS_IO_DXXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "1101" else '1'; -- I/O Control signals, mainly used for mirroring of the video module registers. - CS_IO_EXXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "1110" + CS_IO_EXXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "1110" else '1'; - CS_IO_FXXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "1111" + CS_IO_FXXn <= '0' when Z80_IORQn = '0' and Z80_M1n = '1' and Z80_ADDR(7 downto 4) = "1111" else '1'; -- 0xF8 set the video mode. [2:0] = mode, 000 = MZ80A, 001 = MZ-700, 010 = MZ-80B, 011 = MZ-800, 111 = Pixel graphics. - CS_FB_VMn <= '0' when CS_IO_FXXn = '0' and Z80_ADDR(3 downto 0) = "1000" + CS_FB_VMn <= '0' when CS_IO_FXXn = '0' and Z80_ADDR(3 downto 0) = "1000" else '1'; -- 0xFD set the Video memory page in block C000:FFFF bit 0, set the CGROM upload access in bit 7. - CS_FB_PAGEn <= '0' when CS_IO_FXXn = '0' and Z80_ADDR(3 downto 0) = "1101" + CS_FB_PAGEn <= '0' when CS_IO_FXXn = '0' and Z80_ADDR(3 downto 0) = "1101" else '1'; -- MZ80B/MZ2000 I/O Registers E0-EB, - CS_80B_PIOn <= '0' when CS_IO_EXXn = '0' and Z80_ADDR(3 downto 2) = "10" and MODE_VIDEO_MZ80B = '1' + CS_80B_PIOn <= '0' when CS_IO_EXXn = '0' and Z80_ADDR(3 downto 2) = "10" and MODE_VIDEO_MZ80B = '1' else '1'; @@ -1498,24 +1547,24 @@ begin -- Mainboard WAIT State Generator S-R latch 4. -- NB: V2.1 design doesnt need the wait state generator as the mapping is done in hardware. -- - --MBWAITGEN: process(SYSCLK, Z80_ADDR, Z80_M1n, CTL_BUSRQn, MEM_MODE_LATCH, Z80_IORQn) + --MBWAITGEN: process(SYSCLK, Z80_ADDR, Z80_M1n, CTL_BUSRQni, MEM_MODE_LATCH, Z80_IORQn) -- variable tmp : std_logic; -- variable iowait : std_logic; --begin -- -- -- IO Wait select active when an IO operation is made in range 0xE0-0xFF. - -- if (Z80_ADDR(7 downto 5) = "111" and Z80_M1n = '1' and CTL_BUSRQn = '1' and MEM_MODE_LATCH(5) = '1' and Z80_IORQn = '0') then + -- if (Z80_ADDR(7 downto 5) = "111" and Z80_M1n = '1' and CTL_BUSRQni = '1' and MEM_MODE_LATCH(5) = '1' and Z80_IORQn = '0') then -- iowait := '0'; -- else -- iowait := '1'; -- end if; -- -- if(SYSCLK='1' and SYSCLK'event) then - -- if((CTL_BUSRQn = '1' and Z80_RESETn = '1') and iowait = '1') then + -- if((CTL_BUSRQni = '1' and Z80_RESETn = '1') and iowait = '1') then -- tmp := tmp; - -- elsif((CTL_BUSRQn = '0' or Z80_RESETn = '0') and iowait = '0') then + -- elsif((CTL_BUSRQni = '0' or Z80_RESETn = '0') and iowait = '0') then -- tmp := 'Z'; - -- elsif((CTL_BUSRQn = '0' or Z80_RESETn = '0') and iowait = '1') then + -- elsif((CTL_BUSRQni = '0' or Z80_RESETn = '0') and iowait = '1') then -- tmp := '1'; -- else -- tmp := '0'; diff --git a/CPLD/SW700/v1.2/tranZPUterSW700_Toplevel.vhd b/CPLD/SW700/v1.2/tranZPUterSW700_Toplevel.vhd index aadc1e7..9f7beb4 100644 --- a/CPLD/SW700/v1.2/tranZPUterSW700_Toplevel.vhd +++ b/CPLD/SW700/v1.2/tranZPUterSW700_Toplevel.vhd @@ -61,7 +61,7 @@ entity tranZPUterSW700 is Z80_CLK : out std_logic; -- K64F control signals. - CTL_BUSACKn : in std_logic; + CTL_BUSACKn : out std_logic; CTL_BUSRQn : in std_logic; CTL_HALTn : out std_logic; CTL_M1n : out std_logic; diff --git a/CPLD/SW700/v1.3/build/tranZPUterSW700_constraints.sdc b/CPLD/SW700/v1.3/build/tranZPUterSW700_constraints.sdc index e203b9c..fb1ed53 100644 --- a/CPLD/SW700/v1.3/build/tranZPUterSW700_constraints.sdc +++ b/CPLD/SW700/v1.3/build/tranZPUterSW700_constraints.sdc @@ -276,7 +276,7 @@ set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}] #set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}] # For both configurations. -#set_false_path -from {cpld512:cpldl512Toplevel|KEY_SUBSTITUTE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} +#set_false_path -from {cpld512:cpldl512Toplevel|KEY_SUBSTITUTE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} set_false_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} set_false_path -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} diff --git a/CPLD/SW700/v1.3/tranZPUterSW700.vhd b/CPLD/SW700/v1.3/tranZPUterSW700.vhd index da524b5..c77eab0 100644 --- a/CPLD/SW700/v1.3/tranZPUterSW700.vhd +++ b/CPLD/SW700/v1.3/tranZPUterSW700.vhd @@ -239,7 +239,7 @@ architecture rtl of cpld512 is signal CPLD_RFSHn : std_logic; -- signal CPLD_HALTn : std_logic; -- signal CTL_BUSRQni : std_logic; -- - signal CTL_BUSACKni : std_logic; -- + signal CTL_BUSACKni : std_logic; -- Buffered BUSACK signal to the K64F to indicate it has control of the bus. signal CTL_BUSGRANTn : std_logic; -- -- RAM select and write signals. @@ -289,10 +289,16 @@ begin -- 111 = MZ-2000 -- [3] - R/W - Mainboard Video - 0 = Enable, 1 = Disable - This flag allows Z-80 transactions in the range D000:DFFF to be directed to the mainboard. When disabled all transactions -- can only be seen by the FPGA video logic. The FPGA uses this flag to enable/disable it's functionality. - -- [4] - R/W - Enable WAIT state during frame display period. 1 = Enable, 0 = Disable (default). The flag enables Z80 WAIT assertion during the frame display period. Most video modes + --*[4] - R/W - Enable WAIT state during frame display period. 1 = Enable, 0 = Disable (default). The flag enables Z80 WAIT assertion during the frame display period. Most video modes -- use double buffering so this isnt needed, but use of direct writes to the frame buffer in 8 colour mode (ie. 640x200 or 320x200 8 colour) there -- is not enough memory to double buffer so potentially there could be tear or snow, hence this optional wait generator. + -- [6:5] - R/W - Mainboard/CPU clock. + -- 000 = Sharp MZ80A 2MHz System Clock. + -- 001 = Sharp MZ80B 4MHz System Clock. + -- 010 = Sharp MZ700 3.54MHz System Clock. + -- 011 -111 = Reserved, defaults to 2MHz System Clock. -- [7] - R/W - Preserve configuration over reset (=1) or set to default on reset (=0). + -- * = SW v2.2 MZ80A only, not used in other CPLD versions. -- MACHINEMODE: process( Z80_CLKi, Z80_RESETn, CS_CPU_CFGn, CS_CPLD_CFGn, CPLD_ADDR, CPLD_DATA_IN, CPLD_CFG_DATA, CPU_CFG_DATA ) begin @@ -632,6 +638,8 @@ begin -- 29 - All memory and IO are on the tranZPUter board, 64K block 5 selected. -- 30 - All memory and IO are on the tranZPUter board, 64K block 6 selected. -- 31 - All memory and IO are on the tranZPUter board, 64K block 7 selected. + -- + -- * = Only on SW-700 v1.3 MEMORYMGMT: process(CPLD_ADDR, CPLD_WRn, CPLD_RDn, CPLD_IORQn, CPLD_MREQn, CPLD_M1n, Z80_HI_ADDR, VZ80_HI_ADDR, MEM_MODE_LATCH, SYS_BUSACKni, CS_VIDEOn, CS_VIDEO_IOn, CS_IO_DXXn, CS_IO_EXXn, CS_IO_FXXn, CS_CPU_CFGn, CS_CPU_INFOn, MODE_CPLD_MB_VIDEOn) begin diff --git a/software/asm/MZ800_1Z_013B.asm b/software/asm/MZ800_1Z_013B.asm new file mode 100644 index 0000000..db7841c --- /dev/null +++ b/software/asm/MZ800_1Z_013B.asm @@ -0,0 +1,2944 @@ + ORG 0 + ; + ; + ; SHARPMZ - 8 2 1 + ; (ROM contents, lower monitor 0000-0FFF) + ; + ; + ; Input / Output address + ; + ; Printer interface +PCPR: EQU 0FCH ; Z80 / PIO +PLPT: EQU PCPR+3 ; printer data output +PLPTS: EQU PCPR+2 ; printer strobe +PLPTI: EQU PCPR+1 ; printer data port inic +PLPTSI: EQU PCPR+0 ; printer strobe port inic + ; Program sound generator +PPSG: EQU 0F2H ; Prog. Sound Gen. + ; Joystick registers +PJ1: EQU 0F1H ; joystick-2 input port +PJ0: EQU 0F0H ; joystick-1 input port + ; Pallet write +PPAL: EQU 0F0H ; pallet write + ; Memory managerment ports OUT +PMMC6: EQU 0E6H ; condition from hill protection +PMMC5: EQU 0E5H ; protect the hill +PMMC4: EQU 0E4H ; maximum neRAM as far as possible +PMMC3: EQU 0E3H ; ROM up +PMMC2: EQU 0E2H ; ROM down + ; Memory managerment ports OUT / IN +PMMC1: EQU 0E1H ; DRAM up / VRAM pryc +PMMC0: EQU 0E0H ; DRAM up / VRAM + ; Floppy disk +PFD: EQU 0D8H +PFDSIZ: EQU PFD+5 ; floppy side settings +PFDMOT: EQU PFD+4 ; drive on / off +PFDDAT: EQU PFD+3 ; register that +PFDSEC: EQU PFD+2 ; sector register +PFDTRK: EQU PFD+1 ; track register +PFDCTR: EQU PFD+0 ; driving word + ; 8253 I/O. mapped. - interupt, clock, etc. +P8253: EQU 0D4H ; 8253 I / O. Mapped +PCTCC: EQU P8253+3 ; control word 8253 +PCTC2: EQU P8253+2 ; counter 2 +PCTC1: EQU P8253+1 ; counter 1 +PCTC0: EQU P8253+0 ; counter 0 + ; 8255 I/O mapped - klavesnice, joystick, CMT +P8255: EQU 0D0H +PCWR55: EQU P8255+3 ; control word 8255 +PPORTC: EQU P8255+2 ; port C - CMT and control +PKBDIN: EQU P8255+1 ; keyboard input +PKBOUT: EQU P8255+0 ; keyboard strobe + ; GDG I/O ports +PCRTC: EQU 0CFH ; CRTC register +PDMD: EQU 0CEH ; display mod register +PRF: EQU 0CDH ; read format register +PWF: EQU 0CCH ; write format register + ; + ; Memory mapping + ; +MGATE0: EQU 0E008H ; enable / disable music + ; 8253 mem. mapped - Interupt, clock +M8253: EQU 0E004H ; 8253 Mem. Mapped +MCTCC: EQU M8253+3 ; control word 8253 +MCTC2: EQU M8253+2 ; counter 2 +MCTC1: EQU M8253+1 ; counter 1 +MCTC0: EQU M8253+0 ; counter 0 + ; 8255 mem. mapped - klavesnice, joystick, CMT +M8255: EQU 0E000H +MCWR55: EQU M8255+3 ; control word 8255 +MPORTC: EQU M8255+2 ; port C - CMT and control +MKBDIN: EQU M8255+1 ; keyboard input +MKBOUT: EQU M8255+0 ; keyboard strobe + ; + ; definice ASCII konstant +CR: EQU 0DH ; novy line +SPACE: EQU 20H ; gap +ESC: EQU 1BH ; escape +CLS: EQU 16H ; clear the screen +CRD: EQU 0CDH ; CR in display code +NOKEY: EQU 0F0H ; code NO KEY + ; definice adres displaye +ADRCRT: EQU 0D000H ; address MZ-700 VRAM +ADRATB: EQU 0D800H ; the address of the CRS attribute +IMPATB: EQU 71H ; default display attribute + ; priznaky pro podprogramy CMT +CHEAD: EQU 0CCH ; indication of CMT work with header +CDATA: EQU 053H ; ---- "---- with data +CWRITE: EQU 0D7H ; CMT indication write data +CREAD: EQU 0D2H ; --- "--- read" + ; +HBLNK: EQU 50*312+11 ; frequency of line decomposition + ; +INTSRQ: EQU 1038H ; PjpM +INTADR: EQU 1039H ; 038Dh ... bounce from INT (38h) +HEAD: EQU 10F0H ; file control block: +NEWSP: EQU HEAD ; processor tray +FNAME: EQU 10F1H ; filename +FSIZE: EQU 1102H ; length +BEGIN: EQU 1104H ; storage address +ENTRY: EQU 1106H ; start address +OLDSP: EQU 1148H ; used to postpone SP +CONMOD: EQU 1170H ; 0b = alpha / graph, 1b = display +CURSOR: EQU 1171H ; cursor position (row / column) +QATBLN: EQU 1173H ; line join attribute table +AKCHAR: EQU 118EH ; the character under the cursor when the cursor is blinking +CURCH: EQU 1192H ; graphical cursor character +CSRH: EQU 1194H ; position on the line +TMLONG: EQU 1195H ; current length TAPE MARK +MGCRC: EQU 1197H ; checksum for CMT +MGCRCV: EQU 1199H ; checksum verify CMT +AMPM: EQU 119BH ; morning / afternoon flag +EIFLG: EQU 119CH ; EI / DI flag +BPFLG: EQU 119DH ; BEEP ON / OFF flag +TEMPO: EQU 119EH ; tempo for music 0-7 +NOTLEN: EQU 119FH ; length of current sheet music +OKTNUM: EQU 11A0H ; octave number 1,2,3 +FREQ: EQU 11A1H ; frequency of the current tone +IOBUF: EQU 11A3H ; input buffer for GETL +MGBASE: EQU 1200H ; boot address +COLD: EQU 0E800H ; cold start system +RBASE: EQU 0FFF0H ; run the program in RAM + ; + ; + ; MZ-700 monitor services vector + ; +@COLD: JP COLD ; cold start +@GETL: JP GETL ; read a line from KBD +@LETNL: JP LETNL ; CRLF and CRT +@IFNL?: JP IFNL? ; conditional CRLF +@PRNTS: JP PRNTS ; space on CRT +@TAB: JP TAB ; tabulation on CRT +@PRNTC: JP PRNTC ; character on CRT +@MSG: JP MSG ; CRT string +@RST18: JP RST18 ; reported to CRT +@GETKY: JP GETKY ; character from KBD +@BRKEY: JP BRKEY ; test on BREAK +@WHEAD: JP WHEAD ; write headers to CMT +@WDATA: JP WDATA ; write the program to CMT +@RHEAD: JP RHEAD ; read headers from CMT +@RDATA: JP RDATA ; read the program from CMT +@VERIF: JP VERIF ; program comparison +@MELDY: JP MELDY ; melody +@TIMST: JP TIMST ; time setting + DB 0,0 ; called for RST 38H +@RST38: JP INTSRQ ; interrupt service +@TIMRD: JP TIMRD ; read time +@BEEP: JP BEEP ; acoustic signal +@XTEMP: JP XTEMP ; tempo for melodies +@MSTA: JP MSTA ; sound start +@MSTP: JP MSTP ; stopped sound + ; + ; COLD - leftover from the MZ-700 computer + ; + LD SP,NEWSP + IM 1 + CALL @INI55 + CALL BRKEY + JR NC,J0070 ; CTRL or SHIFT + CP 20H + JR NZ,J0070 ; SHIFT, that's uninteresting +GORAM: ; jump to RAM from address 0 + OUT (PMMC1),A ; mapping - end = DRAM + LD DE,RBASE ; where + LD HL,QRUNT ; what + LD BC,5 ; pin + LDIR ; MOVE + JP RBASE ; ... jump + ; +QRUNT: OUT (PMMC0),A ; ... for copying + JP 0 ; jump to RAM + ; +J0070: + LD B,255 ; zero + LD HL,FNAME ; memory info + CALL @F0B ; cartridge block + LD A,CLS + CALL @PRNTC ; clear display + LD A,IMPATB ; default attribute 71H + LD HL,ADRATB ; attribute address in VRAM + CALL @FILLA ; CRT attribute settings + LD HL,@CLOCK ; initialization interrupted + LD A,0C3H ; C3 = JP + LD (INTSRQ),A + LD (INTADR),HL ; the address of the basic interrupt routine + LD A,4 + LD (TEMPO),A ; music tempo initialization + CALL MSTP ; stop music + CALL @IFNL? + LD DE,SMON7 ; introductory message of the monitor + RST 18H + CALL BEEP + LD A,1 +J00A4: + LD (BPFLG),A ; turn off BEEP + LD HL,0E800H ; if it is on the E800h ROM + LD (HL),A ; so there is a sale + JR J0102 + ; + ; Input and display decryption + ; DE .... address of the chain + ; B ..... its length + ; +FPRMPT: + CALL @IFNL? + LD A,'*' ; Reporting sign + CALL @PRNTC + LD DE,IOBUF ; Input buffer address + CALL @GETL ; Honor the display +PRMLOP: LD A,(DE) + INC DE + CP CR + JR Z,FPRMPT ; sell monitor control + CP 'J' + JR Z,FJUMP ; sell control of the program + CP 'L' + JR Z,FLOAD ; upload and run the program + CP 'F' + JR Z,FF???? ; jump up when ROM + CP 'B' + JR Z,FBEEPX ; beep on / off after the character + CP '#' + JR Z,GORAM ; jump to RAM from 0 + CP 'P' + JR Z,FPRINT ; printer operator + CP 'M' + JP Z,FMODIF ; memory modification + CP 'S' + JP Z,FSAVE ; save the program to CMT + CP 'V' + JP Z,FVERIF ; program comparison on CMT + CP 'D' + JP Z,FDUMP ; listing of memory contents + NOP + NOP + NOP + NOP + JR PRMLOP ; the first character is not a display, perhaps another + ; +FJUMP: + CALL FHLHEX ; decode the jump address + JP (HL) ; and sell control + ; +FBEEPX: ; controlled whistling after each character + LD A,(BPFLG) + RRA + CCF + RLA + JR J00A4 + ; +FF????: ; look up + LD HL,0F000H ; if there is something a lot +J0102: ; zajimaveho + LD A,(HL) ; when there is zero, + OR A ; so he won't jump there + JR NZ,FPRMPT ; and when there will be zero + JP (HL) ; so jump right there + ; +FCMTER: ; recognizes and responds + CP 2 ; type of error you + JR Z,FPRMPT ; return routines for + LD DE,SCHECK ; works with CMT: + RST 18H +FPRMP1: ; relative jumps are + JR FPRMPT ; sometimes too short + ; +FLOAD: + CALL RHEAD ; read the program header + JR C,FCMTER + CALL @IFNL? + LD DE,SLOAD ; lists LOADING + RST 18H + LD DE,FNAME ; and the name of the program + RST 18H + CALL RDATA ; read the program + JR C,FCMTER + LD HL,(ENTRY) + LD A,H ; if the start address is + CP MGBASE/256 ; less than 1200H so + JR C,FPRMP1 ; return to the monitor and v + JP (HL) ; otherwise the sale + ; control of the recorded program +FGETL: ; read the row from the keyboard + EX (SP),HL + POP BC + LD DE,IOBUF ; works with standard + CALL @GETL ; I / O buffer + LD A,(DE) + CP ESC ; break? + JR Z,FPRMP1 ; yes, return to monitor + JP (HL) ; no, return + ; +FHLHEX: ; decodes the address in the display + EX (SP),IY ; returned to IY + POP AF ; and out of the cellar + CALL @HLHEX ; try to decode + JR C,FPRMP1 ; not possible, so to the monitor + JP (IY) ; return + ; +SCHECK: DB "CHECK SUM ER." + DB CR +FPRINT: ; dump the rest of the display + LD A,(DE) ; on the printer + CP '&' ; & is a special feature flag + JR NZ,FP ; & was not, list everything +J015A: INC DE ; testing character for & + LD A,(DE) + CP 'L' + JR Z,FPL ; 60 characters per line + CP 'S' + JR Z,FPS ; 80 characters per line + CP 'C' + JR Z,FPC ; exchange per + CP 'G' + JR Z,FPG ; graphically mod + CP 'T' + JR Z,FPT ; test +FP: + CALL FPTEXT + JP FPRMPT + ; +FPL: + LD DE,QPRN2 ; 60 characters per line + JR FP + ; +FPS: + LD DE,QPRN1 ; 80 characters per line + JR FP + ; +FPT: + LD A,4 ; test + JR J0186 + ; +FPG: + LD A,2 ; graphically mod +J0186: CALL FPCHAR + JR J015A + ; +FPC: + LD A,1DH ; exchange per + JR J0186 + ; +FPCHAR: ; print character to LPT + LD C,0 + LD B,A + CALL FPTEST ; check for LPT + LD A,B + OUT (PLPT),A ; after sign + LD A,10000000B + OUT (PLPTS),A ; and confirm it + LD C,1 ; waiting for LPT to be taken over + CALL FPTEST + XOR A + OUT (PLPTS),A ; and match confirmed + RET + ; +FPTEXT: ; print text to a printer + PUSH DE ; in DE is the address + PUSH BC ; the text must end CR + PUSH AF ; and it also prints +PTELOP: LD A,(DE) ; character from the buffer + CALL FPCHAR ; and LPT + LD A,(DE) ; again this character + INC DE ; point to the next + CP CR ; CR was sent + JR NZ,PTELOP ; No, let's go + POP AF ; CR sent, end of + POP BC + POP DE + RET + ; +FPTEST: ; printer readiness test + IN A,(PLPTS) + AND 00001101B + CP C + RET Z ; hura, READY printer + CALL @BRKEY + JR NZ,FPTEST ; when the printer is silent + LD SP,NEWSP ; and BREAK is pressed + JP FPRMPT ; jump to the monitor + ; + ; Plays music stored on DE, terminated by CR, + ; it is there ASCII in the MZ-700 Basic conventions + ; + ; input: DE - string address + ; output: AF + ; +MELDY: + PUSH BC + PUSH DE + PUSH HL + LD A,2 ; standard octave number + LD (OKTNUM),A + LD B,1 +MELOOP: + LD A,(DE) + CP CR ; the end? + JR Z,J0211 ; Yes + CP 0C8H ; or, such an end? + JR Z,J0211 ; Yes + CP 0CFH + JR Z,J0205 ; o oktavu niz + CP '-' + JR Z,J0205 ; o oktavu niz + CP '+' + JR Z,J020D ; o oktavu vys + CP 0D7H + JR Z,J020D ; o oktavu vys + CP '#' + LD HL,MTBL + JR NZ,J01F5 ; normal tons + LD HL,MTBLS + INC DE ; pultony +J01F5: CALL @MELTB ; look for the note + JR C,MELOOP ; not found + CALL @MELW ; wait for the end last time + JR C,J0214 ; BREAK + CALL MSTA ; turn on food + LD B,C + JR MELOOP +J0205: LD A,3 ; o oktavu vys +J0207: LD (OKTNUM),A + INC DE + JR MELOOP +J020D: LD A,1 ; o oktavu niz + JR J0207 +J0211: CALL @MELW ; we play +J0214: PUSH AF + CALL MSTP ; and it will no longer be played + POP AF + JP POPX2 ; POP and RET + ; + ; Finds the actual frequency and length in the melody table + ; according to the ASCII chain + ; + ; input: HL - table address + ; DE - address to the music buffer + ; (DE) - ASCII note sought + ; + ; exit: + ; + ; note found: DE = address of next item + ; (FREQ) = frequency 2 bytes + ; C = length of the note + ; A = 0 + ; HL = undefined + ; + ; If the 1st character is not a note number, it returns CY = 1 and adjusts only DE + ; If the 2nd character is not a length, the drive binds the specified length + ; +@MELTB: + PUSH BC + LD B,8 + LD A,(DE) +J0220: CP (HL) ; look in the sheet music + JR Z,J022C + INC HL + INC HL + INC HL + DJNZ J0220 + SCF ; bad note + INC DE + POP BC + RET +J022C: ; we found a note + INC HL + PUSH DE + LD E,(HL) ; frequency to DE + INC HL + LD D,(HL) + EX DE,HL + LD A,H + OR A ; is small ? + JR Z,J023F ; yes, ignore octaves + LD A,(OKTNUM) ; octave number +J0239: DEC A + JR Z,J023F ; finally donated + ADD HL,HL ; multiple of frequency + JR J0239 +J023F: LD (FREQ),HL + LD HL,OKTNUM + LD (HL),2 ; middle octave + DEC HL ; points to the length of the note + POP DE + INC DE + LD A,(DE) ; length of the buffer + LD B,A + AND NOKEY + CP '0' + JR Z,J0255 ; it can be a number + LD A,(HL) ; it's nonsense + JR J025A ; so we go from the last length +J0255: INC DE + LD A,B + AND 0FH + LD (HL),A ; save note length (0-9) +J025A: LD HL,QMELEN ; indexing of the TEMPO table + ADD A,L + LD L,A + LD C,(HL) ; actual length + LD A,(TEMPO) + LD B,A + XOR A +J0265: ADD A,C ; multiply with pace + DJNZ J0265 + POP BC + LD C,A + XOR A + RET + ; + ; melody table for normal notes + ; +MTBL: DB 'C' + DW 2118 + DB 'D' + DW 1887 + DB 'E' + DW 1681 + DB 'F' + DW 1587 + DB 'G' + DW 1414 + DB 'A' + DW 1260 + DB 'B' + DW 1124 + DB 'R' + DW 0 + ; + ; Frequency table for # notes + ; +MTBLS: DB 'C' + DW 1999 + DB 'D' + DW 1781 + DB 'E' + DW 1587 + DB 'F' + DW 1498 + DB 'G' + DW 1335 + DB 'A' + DW 1189 + DB 'B' + DW 1059 + DB 'R' + DW 0 + ; + ; Table of length notes + ; +QMELEN: DB 1,2,3,4,6,8,12,16,24,32 + ; + ; DE = DE + 4 (if it were a macro assembler) + ; +@IC4DE: INC DE + INC DE + INC DE + INC DE + RET + ; + ; Turns on music at (FREQ), + ; writes it to 8253 and executes LD (M GATE0), 1 + ; this will start it + ; +MSTA: + LD HL,(FREQ) ; frequency here + LD A,H + OR A + JR Z,MSTP ; if it is 0 then stop + PUSH DE + EX DE,HL + LD HL,MCTC0 + LD (HL),E ; set frequency + LD (HL),D + LD A,1 ; turn on the music + POP DE + JR J02C4 + ; + ; Stop the music + ; +MSTP: + LD A,36H ; will not be quoted anymore + LD (MCTCC),A + XOR A ; ban music +J02C4: LD (MGATE0),A ; and it goes to GATE 8253 + RET + ; + ; Wait for the melody to finish + ; + ; input: B = length of waiting + ; output: HL = E000 + ; A = 0 + ; CY = 1 ... break + ; 0 ... waited + ; +@MELW: + LD HL,MKBOUT ; key strobe + LD (HL),0F8H + INC HL + LD A,(HL) ; key input + AND 81H + JR NZ,J02D5 ; no one is squeezing anything + SCF ; it was a break + RET +J02D5: LD A,(MGATE0) + RRCA + JR C,J02D5 ; wait for one +J02DB: LD A,(MGATE0) + RRCA + JR NC,J02DB ; wait for zero + DJNZ J02D5 ; and more expectations + XOR A + RET + ; + ; Set melody tempo 0-7 + ; 8-A -M TIME + ; +XTEMP: + PUSH AF + PUSH BC + AND 0FH ; only the lower 4 bits + LD B,A ; we read from eight + LD A,8 + SUB B + LD (TEMPO),A ; and store where it belongs + POP BC + POP AF + RET + ; + ; Returns the display attributes + ; + ; output: HL = cursor position + ; DE = address in the next row table + ; A bit 0 = attribute of the current line + ; A bit 7 = CY = next line attribute + ; +@ATBLN: + LD HL,QATBLN + LD A,(CURSOR+1) ; row number + ADD A,L ; index table + LD L,A + LD A,(HL) ; attribute of our line + INC HL + RL (HL) + OR (HL) ; and complete the attribute + RR (HL) ; dalsiho radku + RRCA ; to the tech bits where it belongs + EX DE,HL + LD HL,(CURSOR) ; current position + RET ; cursor + ; + ; Time setting + ; + ; A = 0 ... in the morning + ; 1 ... in the afternoon + ; + ; DE = number of seconds since the beginning of the field + ; + ; CT1 ... period 1 second (mod 2) + ; CT2 ... period 43200 period CT1 = 12 hours (mod 0) + ; +TIMST: + DI + PUSH BC + PUSH DE + PUSH HL + LD (AMPM),A + LD A,NOKEY + LD (EIFLG),A ; enable disruption + LD HL,43200 + XOR A + SBC HL,DE ; how much is left until 12 + PUSH HL ; so much to hide + NOP + EX DE,HL + LD HL,MCTCC + LD (HL),01110100B ; CT1 mod 2 + LD (HL),10110000B ; CT2 mod 0 + DEC HL + LD (HL),E ; set CT2 + LD (HL),D + DEC HL + LD (HL),10 ; then 10 to CT1 + LD (HL),0 + INC HL + INC HL + LD (HL),10000000B ; CT2 mod 0 latch + DEC HL +J0331: LD C,(HL) ; wait for CT2 + LD A,(HL) ; docita, so far + CP D ; goes fast + JR NZ,J0331 + LD A,C + CP E + JR NZ,J0331 + DEC HL + NOP + NOP + NOP + LD (HL),HBLNK % 256 ; to CT1 is saved + LD (HL),HBLNK/256 ; what belongs there + INC HL + POP DE +J0344: LD C,(HL) ; and we'll wait for CT2 + LD A,(HL) ; either not expected at all or + CP D ; 12 hours + JR NZ,J0344 + LD A,C + CP E + JR NZ,J0344 + POP HL + POP DE + POP BC + EI + RET + ; + ; sheet music for BEEP + ; +QBEEP: DB 0D7H,'A','0',CR +N01U02: DB 0,0 + ; + ; read time in the same format as TIMST + ; +TIMRD: + PUSH HL + LD HL,MCTCC + LD (HL),10000000B ; CT2 mod 0 latch + DEC HL + DI + LD E,(HL) + LD D,(HL) + EI + LD A,E + OR D + JR Z,J0375 ; 0 hours is 12 hours + XOR A + LD HL,43200 ; we really have so much + SBC HL,DE + JR C,J037F ; it can't even happen + EX DE,HL ; if only someone + LD A,(AMPM) ; played with a quote + POP HL + RET +J0375: LD DE,43200 +J0378: LD A,(AMPM) + XOR 1 + POP HL + RET +J037F: DI ; someone played with him, + LD HL,MCTC2 ; that must be explained + LD A,(HL) ; the time is complemented + CPL + LD E,A + LD A,(HL) + CPL + LD D,A + EI + INC DE + JR J0378 + ; + ; Standard interrupt handler routine + ; activates once every 12 hours + ; and switches the AMPM to the second state + ; + ; sets mod 0 to CT2 + ; CT2 = CT2 + 43200 - 2 + ; +@CLOCK: PUSH AF + PUSH BC + PUSH DE + PUSH HL + LD HL,AMPM + LD A,(HL) + XOR 1 ; from morning to afternoon + LD (HL),A ; and from afternoon to morning + LD HL,MCTCC + LD (HL),10000000B ; CT2 mod 0 latch + DEC HL + PUSH HL + LD E,(HL) ; pull time + LD D,(HL) + LD HL,43200 + ADD HL,DE ; + 12 hours + DEC HL ; there is some correction + DEC HL + EX DE,HL ; to DE + POP HL + LD (HL),E ; and stuff back + LD (HL),D + POP HL + POP DE + POP BC + POP AF + EI + RET + ; + ; List of contents (HL) in the nun system, before the byte + ; there will be a gap + ; + ; input: HL = address to memory + ; output: A = (HL) + ; +@MHEX: + CALL PRNTS + LD A,(HL) + CALL @BTHEX + LD A,(HL) + RET + ; + ; Listing HL in the nun system + ; + ; input: HL = number we want to list + ; output: AF + ; +@HEXHL: + LD A,H + CALL @BTHEX + LD A,L + JR @BTHEX + ; + DB 0,0 + ; + ; Output of content A in the colon system + ; + ; input: A = number we want to list + ; output: AF + ; +@BTHEX: + PUSH AF + RRCA + RRCA + RRCA + RRCA + CALL @ASC + CALL @PRNTC + POP AF + CALL @ASC + JP @PRNTC + ; + ; Table setting of 60 characters per line + ; +QPRN1: DB 1,9,9,9,CR + ; + ; Convert the lower four bits of the A register + ; to the hexadecimal digit + ; + ; input: A = lower four bits + ; output: A = corresponding hexadecimal digit + ; (in ASCII) + ; +@ASC: + AND 0FH + CP 10 + JR C,J03E2 + ADD A,'A'-'0'-10 +J03E2: ADD A,'0' + RET + ; + ; Converts a hexadecimal digit to + ; four-bit value + ; + ; input: A = digits in ASCII + ; output: CY = 0 and A = corresponding value + ; CY = 1 cannot convert + ; (in A the value is undefined) + ; +HEX: + SUB '0' + RET C + CP 10 + CCF + RET NC + SUB 'A'-'0'-10 + CP 16 + CCF + RET C + CP 10 + RET + ; +N02U04: DB 0,0,0,0 + ; +@HEX: + JR HEX + ; +SPLAY: DB 7FH + DB " PLAY" + DB CR +SREC: DB 7FH + DB " RECORD." + DB CR + ; +N03U04: DB 0,0,0,0 + ; + ; + ; It stores the value written in the noun in HL + ; system as ASCII characters + ; + ; input: DE = string address + ; output: CY = 0 and HL = corresponding value + ; CY = 1 conversion cannot be performed + ; (HL contains undefined state) + ; +@HLHEX: + PUSH DE + CALL @2HEX + JR C,J041D + LD H,A + CALL @2HEX + JR C,J041D + LD L,A +J041D: POP DE + RET + ; + ; + ; Converts 2 ASCII characters from a string + ; to A as a number in the hexadecimal system + ; + ; input: DE = string address + ; output: CY = 1 error, DE and A contains nedef. state + ; CY = 0 and DE = DE + 1, A = number + ; +@2HEX: + PUSH BC + LD A,(DE) + INC DE + CALL @HEX + JR C,J0434 + RRCA + RRCA + RRCA + RRCA + LD C,A + LD A,(DE) + INC DE + CALL @HEX + JR C,J0434 + OR C +J0434: POP BC + RET + ; + ; Oblast podprogramu pro praci s CMT + ; + ; + ; Write the file header to CMT + ; + ; Output: CY = 1 an error has occurred + ; +WHEAD: + DI + PUSH DE + PUSH BC + PUSH HL + LD D,CWRITE ; sign of the record + LD E,CHEAD ; header flag + LD HL,HEAD ; header storage address + LD BC,128 ; head length +J0444: CALL @CHECK + CALL @MGON + JR C,J0464 ; BREAK while waiting for CMT + LD A,E + CP CHEAD ; if a header is written + JR NZ,J045E ; listing WRITING filename + CALL @IFNL? + PUSH DE + LD DE,SWRITE + RST 18H + LD DE,FNAME + RST 18H + POP DE +J045E: + CALL @WTMRK + CALL @WBLOK +J0464: + JP CMTEND + ; +SWRITE: DB "WRITING ", CR +QPRN2: DB 1,9,9,11,CR + ; + ; Write the program on CMT + ; + ; CY = 1 an error has occurred + ; +WDATA: + DI + PUSH DE + PUSH BC + PUSH HL + LD D,CWRITE ; sign of the record + LD E,CDATA ; program flag + LD BC,(FSIZE) ; program length + LD HL,(BEGIN) ; the beginning of the program + LD A,B ; this information is taken + OR C ; from the file header + JR Z,POPX1 ; length = 0 =M POP and RET + JR J0444 ; + ; + ; Write a block of data to the CMT + ; It assumes the tape recorder is turned on and saved + ; TAPE MARK and the existence of a checksum + ; at the standard MGCRC address + ; + ; input: HL = data block storage address + ; BC = its length + ; output: CY = 1 an error has occurred + ; +@WBLOK: + PUSH DE + PUSH BC + PUSH HL ; all data is saved + LD D,2 ; on CMT twice + LD A,11111000B ; Key strobe for advice with BREAK + LD (MKBOUT),A +WBLOOP: LD A,(HL) + CALL @WBYTE + LD A,(MKBDIN) ; octeni keyboard + AND 10000001B ; test on BREAK + JP NZ,J04A5 + LD A,2 ; if BREAK was detected + SCF ; set A = 2, CY = 1 + JR POPX1 ; and POP and RET are performed +J04A5: INC HL + DEC BC + LD A,B ; and is stored until + OR C ; neni BC = 0 + JP NZ,WBLOOP + LD HL,(MGCRC) ; read the control + LD A,H ; respect and its imposition + CALL @WBYTE ; and CMT + LD A,L + CALL @WBYTE + CALL @MG1 ; write last bit = 1 + DEC D ; should I save one more time? + JP NZ,J04C2 ; Yes + OR A ; resets CY + JP POPX1 ; POP and RET + ; +J04C2: LD B,0 ; will be saved again +J04C4: CALL @MG0 ; will send to CMT + DEC B ; 256 times zero + JP NZ,J04C4 + POP HL ; the contents of the registry are restored + POP BC + PUSH BC + PUSH HL + JP WBLOOP ; and we're going for it again + ; +POPX1: POP HL + POP BC + POP DE + RET + ; + DB 0EH,0 ; someone forgot this here + ; + ; Read headers from CMT + ; + ; Output: CY = 1 an error has occurred + ; A = 1 checksum error + ; A = 2 detected BREAK + ; CY = 0 OK + ; (content A is undefined) + ; +RHEAD: + DI + PUSH DE + PUSH BC + PUSH HL + LD D,CREAD ; reading flag + LD E,CHEAD ; header flag + LD BC,128 ; head length + LD HL,HEAD ; header storage address +J04E6: CALL @MGON + JP C,CMTBRK ; error + CALL @RTMRK + JP C,CMTBRK ; error + CALL @RBLOK + JP CMTEND + ; + ; Read the program from the CMT according to the information + ; stored in the header + ; + ; output: CY with the meaning as for RHEAD + ; +RDATA: + DI + PUSH DE + PUSH BC + PUSH HL + LD D,CREAD ; reading flag + LD E,CDATA ; program flag + LD BC,(FSIZE) ; program length + LD HL,(BEGIN) ; boot address + LD A,B ; if it is a length + OR C ; zero, so be it + JP Z,CMTEND ; does not record anything + JR J04E6 + ; + ; Read a block of data from the CMT + ; + ; input: BC = data block length + ; HL = storage address + ; output: CY with the meaning as for RHEAD + ; +@RBLOK: + PUSH DE + PUSH BC + PUSH HL + LD H,2 ; try to clean 2 blocks +J0513: LD BC,MKBDIN + LD DE,MPORTC +J0519: CALL W0TO1 ; wait for the edge + JR C,CMTBRK ; did not reach + CALL @D331 ; pocka and READ POINT + LD A,(DE) ; she made a sample + AND 00100000B ; is it zero? + JP Z,J0519 ; Yes + LD D,H + LD HL,0 + LD (MGCRC),HL ; resets the CRC + POP HL ; restore registries + POP BC + PUSH BC + PUSH HL +J0532: CALL @RBYTE + JR C,CMTBRK ; error + LD (HL),A + INC HL + DEC BC + LD A,B ; until BC = 0 + OR C ; so read + JR NZ,J0532 + LD HL,(MGCRC) + CALL @RBYTE ; read the CRC + JR C,CMTBRK ; error + LD E,A + CALL @RBYTE + JR C,CMTBRK ; error + CP L + JR NZ,J0565 ; if the CRC does not agree + LD A,E ; so he jumps off + CP H + JR NZ,J0565 +J0553: XOR A ; A = 0, CY = 0 + ; + ; Here I jump all routines for CMT operation + ; CMT is turned off here, enable interrupt if it is + ; Enable interrupt enabled and perform nqvrat + ; +CMTEND: POP HL + POP BC + POP DE + CALL @MGOFF ; turn off CMT + PUSH AF + LD A,(EIFLG) + CP NOKEY ; when music is on + JR NZ,J0563 ; so you are allowed to interrupt + EI +J0563: POP AF + RET + ; +J0565: DEC D ; can i try to clean? + JR Z,J056E ; no -M + LD H,D ; Yes + CALL @RINTR ; skip the zero area + JR J0513 ; and I'm going for it again + ; +J056E: LD A,1 ; checksum error + JR J0574 + ; +CMTBRK: LD A,2 ; detected BREAK +J0574: SCF + JR CMTEND + ; + ; Acoustic signal + ; + ; Nici: AF + ; +BEEP: + PUSH DE + LD DE,QBEEP + RST 30H ; P=M CALL MELDY + POP DE + RET + ; + ; Click the cursor and test the KBD in the display code, + ; + ; output: A = read character + ; Z = 1 ... key not pressed + ; +@?KBDC: + CALL BLIKC + CALL @GETKD + CP NOKEY + RET + DB 0 + ; + ; Just a trap program with facts in mind + ; + ; output: CY = 1 an error has occurred + ; A = 1 checksum error + ; A = 2 detected BREAK + ; CY = 0 OK + ; (content A is undefined) + ; +VERIF: + DI + PUSH DE + PUSH BC + PUSH HL + LD BC,(FSIZE) ; program length + LD HL,(BEGIN) ; address of the beginning of the program + LD D,CREAD ; reading flag + LD E,CDATA ; program flag + LD A,B + OR C ; when the length is zero + JR Z,CMTEND ; so nothing happens + CALL @CHECK + CALL @MGON + JR C,CMTBRK ; error + CALL @RTMRK + JR C,CMTBRK ; error + CALL @VBLOK + JR CMTEND + ; + ; Verifies a block of data from the CMT + ; + ; Input: HL = data block address + ; BC = length of the data + ; Output: CY with the meaning of VERIF + ; +@VBLOK: + PUSH DE + PUSH BC + PUSH HL + LD H,2 +J05B2: LD BC,MKBDIN + LD DE,MPORTC +J05B8: CALL W0TO1 ; wait for the edge + JP C,CMTBRK ; did not reach + CALL @D331 + LD A,(DE) + AND 00100000B + JP Z,J05B8 ; it is not a LONG bit + LD D,H + POP HL ; restore the registry + POP BC + PUSH BC + PUSH HL +J05CC: CALL @RBYTE ; read until BC = 0 + JR C,CMTBRK ; error + CP (HL) + JR NZ,J056E ; error + INC HL + DEC BC + LD A,B + OR C + JR NZ,J05CC + LD HL,(MGCRCV) + CALL @RBYTE ; read checksum + CP H + JR NZ,J056E ; error + CALL @RBYTE + CP L + JR NZ,J056E ; error + DEC D ; I still have to check + JP Z,J0553 ; one block? + LD H,D ; Yes + JR J05B2 ; I'm on it + ; + ; Turns off the cursor + ; character (AKCHAR) da at the cursor position, it was there + ; hidden by the @CURON subroutine + ; + ; output: HL = cursor address + ; +@CUROF: + PUSH AF + LD A,(AKCHAR) + CALL @?POINT + LD (HL),A + POP AF + RET + ; + ; Prints the HL address on a new CRT line + ; + ; input: HL = displayed word + ; output: AF + ; +@?NLHL: + CALL @IFNL? + CALL @HEXHL + RET + ; + ; Waiting for the leading edge of the signal from the CMT + ; + ; input: BC =M KBDIN + ; DE =M PORTC + ; output: CY = 0 reached + ; CY = 1 was BREAK + ; output: AF + ; +W0TO1: + LD A,11111000B ; strobe keyboard + LD (MKBOUT),A + NOP ; they forgot something here again +J0607: LD A,(BC) + AND 10000001B ; is a break? + JR NZ,J060E ; No + SCF ; Yes + RET + ; +J060E: LD A,(DE) ; we are waiting for zero from CMT + AND 00100000B + JR NZ,J0607 +J0613: LD A,(BC) ; when we got there + AND 10000001B ; so we will test BREAK + JR NZ,J061A ; and let's go + SCF ; was BREAK + RET + ; +J061A: LD A,(DE) ; we are waiting for one + AND 00100000B + JR Z,J0613 ; and we test it + RET ; BREAK + ; + DB 0,0,0,0 + ; + ; Read the apartment from CMT + ; + ; Output: CY = 0 and A contains the read byte + ; CY = 1 was detected by BREAK + ; (content A is not defined) + ; +@RBYTE: + PUSH BC + PUSH DE + PUSH HL + LD HL,8*256+0 ; in H is the number of bits in the byte + LD BC,MKBDIN ; preparation of values + LD DE,MPORTC ; for W0TO1 +J0630: CALL W0TO1 + JP C,J0654 ; error, POP and RET + CALL @D331 ; waiting for READ POINT + LD A,(DE) + AND 00100000B ; sampled + JP Z,J0649 ; for zero it is skipped + PUSH HL ; checksum + LD HL,(MGCRC) + INC HL + LD (MGCRC),HL + POP HL + SCF +J0649: LD A,L ; stores the value in L + RLA ; read bit + LD L,A + DEC H ; has it been 8 bits? + JP NZ,J0630 ; No + CALL W0TO1 ; if so, wait + LD A,L ; to the leading edge of another +J0654: POP HL ; signal, save the read + POP DE ; value to the A register + POP BC ; and end up + RET + ; + DB 0,0,0 + ; + ; Skip loading tons + ; and pocka on TAPE MARK + ; + ; Input: E = 0CCH as header flag + ; or E = anything other than + ; program flag + ; + ; Output: CY = 1 detected BREAK + ; CY = 0 OK + ; Nici: AF + ; +@RTMRK: + CALL @RINTR ; skip bootloader + PUSH BC ; tone + PUSH DE + PUSH HL + LD HL,40*256+40 + LD A,E ; produce to H and L + CP CHEAD ; lengths LONG and SHORT + JR Z,J066C ; areas in TAPE MARK + LD HL,20*256+20 ; according to the symptom of E +J066C: LD (TMLONG),HL ; and hide them + LD BC,MKBDIN ; initializes values + LD DE,MPORTC ; for W0TO1 +J0675: LD HL,(TMLONG) ; restores the length of TAPE MARK +J0678: CALL W0TO1 + JR C,POPX2 ; error + CALL @D331 ; pocka to READ POINT + LD A,(DE) + AND 00100000B ; is sampled + JR Z,J0675 ; it's zero and now it's waiting + DEC H ; to ones =M again + JR NZ,J0678 ; can continue +J0688: CALL W0TO1 ; and now he will wait + JR C,POPX2 ; to block zero + CALL @D331 + LD A,(DE) + AND 00100000B + JR NZ,J0675 ; the one read + DEC L + JR NZ,J0688 + CALL W0TO1 ; wait for the leading edge +POPX2: POP HL ; the following signal + POP DE + POP BC + RET + ; + ; Turn on the tape recorder + ; + ; input: D = D2 as read flag + ; or anything else + ; as a sign of writing + ; output: CY = 1 BREAK detected + ; CY = 0 OK + ; +@MGON: + PUSH BC + PUSH DE + PUSH HL + LD B,10 ; number of power-up attempts +J06A4: LD A,(MPORTC) + AND 00010000B ; is it going + JR Z,J06B9 ; No +J06AB: LD B,255 ; if so then take a moment +J06AD: CALL @D7000 ; pocka na motor + JR J06B4 ; about 1.8 secondsQ + ; + JR @MGON ; they forgot something here, IT'S NOWQ + ; +J06B4: DJNZ J06AD + XOR A +J06B7: JR POPX2 ; and we're leaving + ; +J06B9: LD A,00000110B ; this sequence instruction + LD HL,MCWR55 ; after the signal + LD (HL),A ; ENGINE edge that would + INC A ; she should have run it if + LD (HL),A ; the drive is on + DJNZ J06A4 + CALL @IFNL? ; it failed at ten + LD A,D ; experiment and so it is written + CP CWRITE ; prompt 'RECORD.PLAY' + JR Z,J06D0 ; respectively 'PLAY' + LD DE,SPLAY + JR J06D7 +J06D0: LD DE,SREC + RST 18H + LD DE,3FDH +J06D7: RST 18H +J06D8: LD A,(MPORTC) ; and will wait for + AND 10H ; until the CMT user turns on + JR NZ,J06AB ; he succeeded + CALL BRKEY ; BREAK? + JR NZ,J06D8 ; no, wait + SCF ; Yes + JR J06B7 ; balime to + ; +SMON7: DB "** MONITOR 1Z-013B **" + DB CR + ; + DB 0 + ; + ; Turns off CMT + ; + ; Protects all registries + ; +@MGOFF: + PUSH AF + PUSH BC + PUSH DE + LD B,10 ; number of attempts +J0705: LD A,(MPORTC) + AND 00010000B ; has he stopped yet? + JR Z,J0717 ; yes, we are + LD A,00000110B ; No, we're sending him + LD (MCWR55),A ; food + INC A + LD (MCWR55),A ; and when it doesn't work either + DJNZ J0705 ; tenth attempt, so +J0717: JP J0EE6 ; it will be left flat + ; + ; Counts the checksum of the data block + ; and save it to the default addresses + ; MGCRC and MGCRCV + ; + ; input: HL = data block address + ; BC = its length + ; +@CHECK: + PUSH BC + PUSH DE + PUSH HL + LD DE,0 ; at the beginning is a control +J0720: LD A,B ; the sum is equal to zero + OR C ; are we done yet? + JR NZ,J072F ; not yet, it's time to work + EX DE,HL + LD (MGCRC),HL ; so let's save it + LD (MGCRCV),HL ; and we will return + POP HL + POP DE + POP BC + RET +J072F: LD A,(HL) ; this is where the CRC of the apartment took place + PUSH BC + LD B,8 ; number of bits in the apartment +J0733: RLCA + JR NC,J0737 + INC DE ; added +J0737: DJNZ J0733 ; I'll finish it for the apartment + POP BC + INC HL ; edit addresses + DEC BC ; and I'm going for it again + JR J0720 + ; + ; Initialization routine + ; + ; sets I8255 to mode 0 + ; And, Cl as an exit + ; B, Ch as input + ; sends an edge to the MOTOR signal + ; so turn it on if + ; was turned off and vice versa + ; allows periodic interrupts + ; from timer I8253 + ; + ; output: HL + ; +@INI55: + LD HL,MCWR55 + LD (HL),10001010B ; mode 8255 + LD (HL),00000111B ; switch CMT + LD (HL),00000101B ; allow interupt + RET + ; + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; + ; Delay approx. 111 microseconds + ; + ; output: AF + ; +@D111: + LD A,27 +J075B: DEC A + JP NZ,J075B + RET + ; + ; Delay about 103 microseconds + ; + ; output: AF + ; +@D103: + LD A,25 +J0762: DEC A + JP NZ,J0762 + RET + ; + ; Writes a byte from the A register to the CMT + ; + ; output: AF + ; +@WBYTE: + PUSH BC + LD B,8 ; number of bits in the apartment + CALL @MG1 ; start / stop bit +J076D: RLCA + CALL C,@MG1 + CALL NC,@MG0 + DEC B + JP NZ,J076D + POP BC + RET + ; + ; Writes the boot signal and TAPE MARK + ; + ; input: E = 0CCH as header flag, or + ; any value, as a program flag + ; output: AF + ; +@WTMRK: + PUSH BC + PUSH DE + LD A,E + LD BC,22000 + LD DE,40*256+40 + CP CHEAD ; according to the symptom + JP Z,J078E ; you set up + LD BC,11000 ; parameters + LD DE,20*256+20 +J078E: CALL @MG0 ; writes BC times zero + DEC BC + LD A,B + OR C + JR NZ,J078E +J0796: CALL @MG1 ; writes D times to one + DEC D + JR NZ,J0796 +J079C: CALL @MG0 ; writes E times a unit + DEC E + JR NZ,J079C + CALL @MG1 + POP DE + POP BC + RET + ; + ; Execute part of the MODIFY display + ; +FMODIF: + CALL FHLHEX ; entered address +FMOD1: + CALL @?NLHL ; write it on a new line + CALL @MHEX ; and a flat on it with a space + CALL PRNTS + CALL FGETL ; honor string character + CALL @HLHEX ; and immediately get a HEXA number from it + JR C,J07D7 ; that should be our address + CALL @IC4DE + INC DE + CALL @2HEX ; and this is old content + JR C,FMOD1 ; it was not a hexadecimal number + CP (HL) ; + JR NZ,FMOD1 ; the old contents do not fit + INC DE + LD A,(DE) + CP CR + JR Z,J07D4 ; only CR pressed + CALL @2HEX ; new content + JR C,FMOD1 ; incorrect entry + LD (HL),A ; modify in memory +J07D4: INC HL ; next byte + JR FMOD1 ; and again +J07D7: LD H,B + LD L,C + JR FMOD1 + ; +QT????: DB 'N','K',CR,';',CR,';',CR,';',' ',' ',' ' + ; + ; + ; Reads the character string from the keyboard. + ; When reading a character, it stores it in VRAM, it is possible + ; use all allowable editing commands + ; (arrows, tab, inst, del, clr, home, etc.) + ; Enter the string at the end by pressing CR, then read, working + ; 40 or 80 character line (depending on the line attribute) + ; to the input buffer, the rest of the line to 40 or 80 + ; is filled with the constant CR. + ; + ; AttentionQ The subroutine saves the line from the beginning, + ; namely the one on which CR was pressed, at the beginning + ; the cursor position does not matter at allQ + ; + ; input: DE = I / O buffer address + ; +GETL: PUSH AF + PUSH BC + PUSH HL + PUSH DE +GETLOP: CALL @??KEY ; flash the cursor and honor KBD + PUSH AF + LD B,A + LD A,(BPFLG) + RRCA + CALL NC,BEEP ; pipni, when you have + LD A,B + LD HL,CONMOD ; NO ONE SETTINGS + AND NOKEY ; DOES NOT NEED + CP 0C0H ; driving sign? + POP DE + LD A,B + JR NZ,J0818 ; no, send + CP 0CDH + JR Z,J085B ; CR came, finally the end + CP 0CBH + JP Z,J0822 ; BREAK + CP 0CFH + JR Z,J0818 ; CF is always written (PROC?) + CP 0C7H + JR NC,J081D ; larger than C6 is controlled + RR E ; A NENSI SNAD NE ?Q + LD A,B + JR NC,J081D +J0818: CALL @AVRAM ; character to VRAM + JR GETLOP +J081D: CALL @?DPCT ; management + JR GETLOP +J0822: POP HL ; BREAK at GETL + PUSH HL + LD (HL),ESC + INC HL + LD (HL),CR + JR J087E ; new line, POP and RET +J082B: RRCA + JR NC,J0865 ; the starting point of the line + JR J0863 ; continued to reach the line + ; + ; Wait 7 milliseconds and honor the keyboard via KBDIN + ; +@WGKEY: + CALL @D7000 + CALL @KBDIN + RET + ; + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; +J085B: + CALL @ATBLN + LD B,40 ; 40 characters per line + JR NC,J082B ; the starting point is line + DEC H ; o line vys +J0863: LD B,80 ; 80 characters per line +J0865: LD L,0 + CALL @?ACUR ; decode the address from the position + POP DE ; address I / O buf + PUSH DE +J086C: LD A,(HL) ; we transfer characters to the I / O buffer + CALL @?DACN + LD (DE),A + INC HL + INC DE + DJNZ J086C + EX DE,HL +J0876: LD (HL),CR ; the spaces at the end will replace CR + DEC HL + LD A,(HL) + CP SPACE + JR Z,J0876 +J087E: CALL LETNL ; new line and end of GETL + POP DE + POP HL + POP BC + POP AF + RET + ; +N07U14: DB 0,0,0,0,0,0,0,0,0,0,0,0,0 + ; + ; Send the character string to the CRT terminated CR + ; control characters (C0-CF) + ; + ; input: DE = string address + ; +MSG: + PUSH AF + PUSH BC + PUSH DE +MSGLOP: + LD A,(DE) ; character from the buffer + CP CR ; is it CR? + JR Z,J08A7 ; it's CR + CALL PRNTC ; it's not CR + INC DE ; to the next sign + JR MSGLOP ; and again + ; + ; Send the character string to the CRT, terminated CR + ; control characters are converted to display code + ; and save to VRAM + ; + ; input: DE = string address + ; +RST18: + PUSH AF + PUSH BC + PUSH DE +J08A4: LD A,(DE) + CP CR +J08A7: JP Z,J0EE6 ; POP and RET + CALL @?ADCN + CALL @PRNTA + INC DE + JR J08A4 + ; +J08B3: LD DE,QKBDS ; close to GETKD + JR J08FA + ; +J08B8: LD A,0CBH + OR A + JR J08D6 + ; + ; Returns the code of the just pressed key in ASCII code, + ; if no was pressed, it returns 0 + ; (call GETKD and then? DACN) + ; + ; output: key in "ASCII" code + ; +GETKY: + CALL @GETKD + SUB NOKEY + RET Z + ADD A,NOKEY + JP @?DACN + ; + DB 0,0 + ; + ; Returns the currently pressed key in the display code to A reg. + ; (this routine has a delay of 7 millisecondsQ) + ; + ; SHIFT + BREAK = CD + ; rear key = F0 + ; common key = code from tablesQ KBD .. + ; + ; mod SHIFT CTRL table + ; + ; ALPHA no no KBD base table + ; ALPHA yes - KBDS shifted charactersQ + ; --- no yesQ KBDC control characters + ; GRAPH no noQ KBDG graphics + ; GRAPH yes -Q KBDGS shifted graphic characters + ; +@GETKD: + PUSH BC + PUSH DE + PUSH HL + CALL @WGKEY ; key pressed + LD A,B ; "shift" keys + RLCA ; the key was pressed + JR C,J08DA ; Yes + LD A,NOKEY ; no, it returns code +J08D6: POP HL ; rear keys + POP DE + POP BC + RET + ; something pressed +J08DA: LD DE,QKBD + LD A,B + CP 88H ; was it a break? + JR Z,J08B8 ; Yes + LD H,0 + LD L,C + BIT 5,A + JR NZ,J08F7 ; driving sign + LD A,(CONMOD) + RRCA + JP C,J08FE ; graphically mod + shift + LD A,B + RLA + RLA + JR C,J08B3 ; shift + JR J08FA ; ordinary character +J08F7: LD DE,QKBDC +J08FA: ADD HL,DE ; index the table +J08FB: LD A,(HL) ; sign here + JR J08D6 ; and the end +J08FE: BIT 6,B + JR Z,J0909 + LD DE,QKBDGS + ADD HL,DE + SCF + JR J08FB +J0909: LD DE,QKBDG + JR J08FA + ; + ; New line on CRT + ; no AF + ; +LETNL: + XOR A + LD (CSRH),A + LD A,CRD + JR J0959 + ; + DB 0,0 + ; + ; New line on CRT, if CSRH PM 0, + ; i.e. if the cursor is not on the edge of the line + ; +IFNL?: + LD A,(CSRH) ; logical cursor position + OR A + RET Z ; we are at the beginning of the line + JR LETNL ; business CR + ; + DB 0 + ; + ; + ; Mezara on display + ; no AF + ; +PRNTS: + LD A,SPACE + JR PRNTC + ; + ; Tab on CRT, then NULL + ; tabs by 10 characters + ; + ; no AF + ; +TAB: + CALL @PRNTS + LD A,(CSRH) + OR A + RET Z ; at the beginning of the line +J092C: SUB 10 ; module 10 = 0? + JR C,TAB ; Yes + JR NZ,J092C ; no, another space + NOP + NOP + NOP + ; + ; Character output to CRT + ; (via PRNTA or? DPCT) + ; + ; input: A = output character + ; output: AF + ; +PRNTC: + CP CR + JR Z,LETNL ; CR is done differently + PUSH BC + LD C,A + LD B,A + CALL FPRNTC ; own routine + LD A,B + POP BC + RET + ; +MSGOK: DB "OK!" + DB CR + ; + ; PRNTC without registry hiding + ; +FPRNTC: LD A,C + CALL @?ADCN ; to display + LD C,A + CP NOKEY + RET Z ; it's nothing + AND NOKEY + CP 0C0H ; rizeni? + LD A,C + JR NZ,@PRNTA ; No + CP 0C7H ; really driving? + JR NC,@PRNTA ; No +J0959: CALL @?DPCT ; it's driving + CP 0C3H ; C right? + JR Z,@ICSRH + CP 0C5H ; home? + JR Z,J0967 + CP 0C6H ; clear? + RET NZ +J0967: XOR A ; at clear a home +J0968: LD (CSRH),A + RET + ; + ; Character from A in the display code directly to VRAM and + ; move CSRH + ; + ; input: A = character in the display code + ; output: AF + ; +@PRNTA: + CALL @AVRAM +@ICSRH: + LD A,(CSRH) ; CSRH increment + INC A + CP 50H + JR C,J0968 + SUB 50H + JR J0968 + ; +J097B: LD A,(AKCHAR) ; piece from BLIKC + JR J09EF + ; +J0980: BIT 5,A ; it's a piece of BRKEY + JR Z,J0986 + OR A ; common characters + RET +J0986: LD A,20H ; CTRL + OR A + SCF + RET + ; +SFNAME: DB "FILENAME? " + DB CR + ; + ; Delay approx. 7 milliseconds + ; + ; output: AF + ; +@D7000: + PUSH BC + LD B,21 +J0999: CALL @D331 + DJNZ J0999 + POP BC + RET + ; +SLOAD: DB "LOADING " + DB CR + ; + ; Delay approx. 459 microseconds + ; + ; output: AF + ; +@D459: + LD A,73H +J09AB: DEC A + JP NZ,J09AB + RET + ; + DB 0,0,0 + ; + ; + ; Flash with the cursor and wait for the keyboard + ; +@??KEY: + PUSH HL + CALL @CURON ; deploy cursor +J09B7: CALL @?KBDC ; wait for the keyboard to release + JR NZ,J09B7 +J09BC: CALL @?KBDC ; wait for the key to be pressed + JR Z,J09BC + LD H,A ; keys in the display + CALL @D7000 + CALL @GETKD ; after 7 ms again + PUSH AF + CP H + POP HL + JR NZ,J09BC ; it's not the same, the key oscillates + PUSH HL + POP AF + CALL @CUROF ; remove cursor + POP HL + RET + ; + ; Fill 2 kB of memory with zero + ; +@FILL0: + XOR A + ; + ; Fill 2 kB of memory with a constant from A + ; + ; input: HL = memory full address + ; output: HL = HL + 800h + ; BC = 0 + ; A = 0 + ; +@FILLA: + LD BC,800H + PUSH DE + LD D,A +J09DA: LD (HL),D + INC HL + DEC BC + LD A,B + OR C + JR NZ,J09DA + POP DE + RET + ; + ; Flashes with the cursor according to the 6th bit of C port 8255 + ; (there is a cursor flicker frequency) + ; + ; Save to VRAM at the cursor position + ; (CURCH) if 6.bit C was equal to one + ; (AKCHAR) ------ "----- zero + ; +@BLIKC: + PUSH AF + PUSH HL + LD A,(MPORTC) ; cursor bit + RLCA + RLCA + JR C,J097B ; save the normal character + LD A,(CURCH) ; save the cursor character +J09EF: CALL @?POINT + LD (HL),A + POP HL + POP AF + RET + ; + DB 0,0,0,0,0,0,0,0,0 + ; +BLIKC: + JR @BLIKC + ; + ; Enroll in CMT: record "SHORT", + ; which represents the value 0 + ; + ; HIGH ------- --- + ; Q Q Q + ; LOW --- -------- + ; ^ ^ ^ ^ + ; 0 240 ^ 278 + 240 + ; ^ (data is in microseconds) + ; READ POINT: 379 + ; +@MG0: + PUSH AF + LD A,00000011B ; high on CMT + LD (MCWR55),A + CALL @D111 + CALL @D111 + LD A,00000010B ; low on CMT + LD (MCWR55),A + CALL @D111 + CALL @D111 + POP AF + RET + ; + ; Enroll in CMT: entry "LONG", + ; which represents the value 1 + ; + ; + ; HIGH ------------- --- + ; Q ^Q Q + ; LOW --- ^ -------------- + ; ^ ^ ^ ^ + ; 0 ^ 470 494 + 470 + ; ^ (data is in microseconds) + ; READ POINT: 379 + ; +@MG1: + PUSH AF + LD A,00000011B ; high on CMT + LD (MCWR55),A + CALL @D459 + LD A,00000010B ; low on CMT + LD (MCWR55),A + CALL @D459 + POP AF + RET + ; + DB 0,0,0,0,0 + ; + ; Tests the state of the SHIFT, CTRL, and BREAK keys + ; + ; output: A = see following table + ; Z = 1 ... SHIFT + BREAK + ; CY = 1 ... SHIFT or CTRL + ; + ; + ; CTRL SHIFT BREAK CY ZA + ; yes no - 1 0 20H control characters + ; no no no 0 0 7FH common characters + ; no no yes 0 0 3FH ESC + ; - yes no 1 0 40H shift characters + ; - yes yes 0 1 0 SHIFT + BREAK + ; +BRKEY: + LD A,11111000B + LD (MKBOUT),A ; key strobe + NOP + LD A,(MKBDIN) ; key input + OR A + RRA ; shift bit to CY + JP C,J0980 ; there was no shift + RLA + RLA ; break bit to CY + JR NC,J0A48 ; it was a break + LD A,40H ; return code shift + SCF + RET +J0A48: XOR A ; SHIFT + BREAK + RET + ; + ; Delay approx. 331 milliseconds + ; + ; output: AF + ; +@D331: + LD A,82 + JP J0762 + ; + DB 0 + ; + ; Returns the hardware code of the currently pressed key + ; + ; output: B = code of the "shift" keys, see the following + ; table. + ; if the key is pressed, it is set + ; 7 bit B register + ; + ; C = key code + ; LINE * 8 + 7-COLUMN + ; LINE and COLUMN are determined from the table + ; physical connection of the keyboard. + ; The subroutine does not test the last column (F1-F5), + ; the penultimate column only affects the B register + ; If the key has not been pressed, it is not + ; C register changed. + ; + ; CTRL SHIFT BREAK BC + ; + ; - yes yes 88H unchanged + ; yes no - 20H key code + ; - yes no 40H " + ; no no no 0H " + ; + ; + ; 0 1 2 3 4 5 6 7 8 9 + ; + ------------------------------------------------- - + + ; Q Q + ; 7Q blank YQIA 1 \ inst break F1Q + ; Q Q + ; 6Q graph ZRJB 2 ^ del ctrl F2Q + ; Q Q + ; 5Q pound @ SKC 3 - right F3Q + ; Q Q + ; 4Q alpha FTLD 4 sp down F4Q + ; Q Q + ; 3Q tab] UME 5 O left F5Q + ; Q Q + ; 2Q ; VNF 6 9 upQ + ; Q Q + ; 1Q : WOG 7,? Q + ; Q Q + ; 0Q cr XPH 8. / shiftQ + ; Q Q + ; + ------------------------------------------------- - + + ; +@KBDIN: + PUSH DE + PUSH HL + XOR A + LD B,11111000B ; this will start strobing + LD D,A ; 0 -M D + CALL BRKEY + JR NZ,J0A5F ; there was no break + LD D,88H ; code break + JR J0A73 ; POP and RET +J0A5F: JR NC,KBDTST ; unhifted + LD D,A ; shifted, hide + JR KBDTST ; and let's go +J0A64: SET 7,D ; a sign that she was a keyboard +KBDTST: DEC B ; next column tested + LD A,B + LD (MKBOUT),A + CP 0EFH ; koncime? + JR NZ,J0A77 ; No + CP 0F8H ; NONSENSE Q THIS CONDITION + JR Z,KBDTST ; IT WILL NEVER BE FULFILLED +J0A73: LD B,D + POP HL + POP DE + RET +J0A77: LD A,(MKBDIN) + CPL + OR A ; is there something in that column? + JR Z,KBDTST ; it does not look like that, + LD E,A ; we will still need it + LD H,8 + LD A,B + AND 00001111B + RLCA ; multiply 8 + RLCA + RLCA + LD C,A + LD A,E +J0A89: DEC H ; we are looking for the right bit + RRCA + JR NC,J0A89 + LD A,H + ADD A,C + LD C,A + JR J0A64 ; POP and RET + ; + ; "ASCII to display" conversion table + ; +QADCN: + DB NOKEY,NOKEY,NOKEY,0F3H,NOKEY,0F5H,NOKEY,NOKEY + DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB NOKEY,0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,NOKEY + DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB 000H,061H,062H,063H,064H,065H,066H,067H + DB 068H,069H,06BH,06AH,02FH,02AH,02EH,02DH + DB 020H,021H,022H,023H,024H,025H,026H,027H + DB 028H,029H,04FH,02CH,051H,02BH,057H,049H + DB 055H,001H,002H,003H,004H,005H,006H,007H + DB 008H,009H,00AH,00BH,00CH,00DH,00EH,00FH + DB 010H,011H,012H,013H,014H,015H,016H,017H + DB 018H,019H,01AH,052H,059H,054H,050H,045H + DB 0C7H,0C8H,0C9H,0CAH,0CBH,0CCH,0CDH,0CEH + DB 0CFH,0DFH,0E7H,0E8H,0E5H,0E9H,0ECH,0EDH + DB 0D0H,0D1H,0D2H,0D3H,0D4H,0D5H,0D6H,0D7H + DB 0D8H,0D9H,0DAH,0DBH,0DCH,0DDH,0DEH,0C0H + DB 080H,0BDH,09DH,0B1H,0B5H,0B9H,0B4H,09EH + DB 0B2H,0B6H,0BAH,0BEH,09FH,0B3H,0B7H,0BBH + DB 0BFH,0A3H,085H,0A4H,0A5H,0A6H,094H,087H + DB 088H,09CH,082H,098H,084H,092H,090H,083H + DB 091H,081H,09AH,097H,093H,095H,089H,0A1H + DB 0AFH,08BH,086H,096H,0A2H,0ABH,0AAH,08AH + DB 08EH,0B0H,0ADH,08DH,0A7H,0A8H,0A9H,08FH + DB 08CH,0AEH,0ACH,09BH,0A0H,099H,0BCH,0B8H + DB 040H,03BH,03AH,070H,03CH,071H,05AH,03DH + DB 043H,056H,03FH,01EH,04AH,01CH,05DH,03EH + DB 05CH,01FH,05FH,05EH,037H,07BH,07FH,036H + DB 07AH,07EH,033H,04BH,04CH,01DH,06CH,05BH + DB 078H,041H,035H,034H,074H,030H,038H,075H + DB 039H,04DH,06FH,06EH,032H,077H,076H,072H + DB 073H,047H,07CH,053H,031H,04EH,06DH,048H + DB 046H,07DH,044H,01BH,058H,079H,042H,060H + + ; + ; Physically place the cursor on the screen. Save the code to + ; variable CURCH = FE ... graphically cursor + ; FF ... alphanumeric cursor + ; The sign that he covered is put to AKCHAR, there you have it + ; they pick up the BLIKC and CUROF routines + ; + ; output: HL = E000H + ; A = FFH + ; +@CURON: + LD HL,CURCH + LD (HL),0EFH ; alphanumeric cursor + LD A,(CONMOD) + RRCA + JR C,J0BA0 ; graphically mod + RRCA ; do I display the cursor? + JR NC,J0BA2 ; No +J0BA0: LD (HL),0FFH ; graphically cursor +J0BA2: LD A,(HL) ; cursor character here + PUSH AF + CALL @?POINT ; cursor address + LD A,(HL) ; what was there + LD (AKCHAR),A ; is hiding for CUROF + POP AF ; a nas cursor + LD (HL),A ; will be stored there + XOR A + LD HL,MKBOUT + LD (HL),A + CPL + LD (HL),A + RET + ; + DB 36H,43H,18H,0E9H + ; + ; Character conversion from "ASCII" code to display code + ; + ; input: A - character in "ASCII" code + ; output: A - character in the display code + ; +@?ADCN: + PUSH BC + PUSH HL + LD HL,QADCN ; asci table -M display + LD C,A + LD B,0 + ADD HL,BC ; index it + LD A,(HL) ; pull out the display code + JR J0BE0 ; POP and RET + ; +SV10A: DB "V1.0A" + DB CR + ; + DB 0,0,0 + ; + ; Convert a character from DISPLAY to an "ASCII" code + ; + ; input: A - character in the display code + ; output: A - character in ASCII code + ; +@?DACN: + PUSH BC + PUSH HL + PUSH DE + LD HL,QADCN ; ASCII table -M display + LD D,H + LD E,L ; and to DE + LD BC,256 ; the length of this table + CPIR ; looking for the sign outside + JR Z,J0BE3 ; found + LD A,NOKEY ; not found, returns NOKEY +J0BDF: POP DE +J0BE0: POP HL + POP BC + RET +J0BE3: OR A ; found, reset CY + DEC HL ; address back + SBC HL,DE ; + LD A,L ; calculate the index from the address + JR J0BDF ; POP and RET + ; + ; Keyboard tables + ; + ; 5 conversion tables from keyboard hardware code to + ; display code, all tables are 64 characters long, + ; only CTRL has only 63 characters for unknown reasons. + ; + ; + ; Normal keys (without SHIFT, CTRL in alphanumeric mode) + ; +QKBD: DB 0BFH,0CAH,058H,0C9H,NOKEY,02CH,04FH,0CDH + DB 019H,01AH,055H,052H,054H,NOKEY,NOKEY,NOKEY + DB 011H,012H,013H,014H,015H,016H,017H,018H + DB 009H,00AH,00BH,00CH,00DH,00EH,00FH,010H + DB 001H,002H,003H,004H,005H,006H,007H,008H + DB 021H,022H,023H,024H,025H,026H,027H,028H + DB 059H,050H,02AH,000H,020H,029H,02FH,02EH + DB 0C8H,0C7H,0C2H,0C1H,0C3H,0C4H,049H,02DH + ; + ; Shift keys + ; +QKBDS: DB 0BFH,0CAH,01BH,0C9H,NOKEY,06AH,06BH,0CDH + DB 099H,09AH,0A4H,0BCH,040H,NOKEY,NOKEY,NOKEY + DB 091H,092H,093H,094H,095H,096H,097H,098H + DB 089H,08AH,08BH,08CH,08DH,08EH,08FH,090H + DB 081H,082H,083H,084H,085H,086H,087H,088H + DB 061H,062H,063H,064H,065H,066H,067H,068H + DB 080H,0A5H,02BH,000H,060H,069H,051H,057H + DB 0C6H,0C5H,0C2H,0C1H,0C3H,0C4H,05AH,045H + ; + ; Normal keys in graphics mode + ; +QKBDG: DB 0BFH,NOKEY,0E5H,0C9H,NOKEY,042H,0B6H,0CDH + DB 075H,076H,0B2H,0D8H,04EH,NOKEY,NOKEY,NOKEY + DB 03CH,030H,044H,071H,079H,0DAH,038H,06DH + DB 07DH,05CH,05BH,0B4H,01CH,032H,0B0H,0D6H + DB 053H,06FH,0DEH,047H,034H,04AH,04BH,072H + DB 037H,03EH,07FH,07BH,03AH,05EH,01FH,0BDH + DB 0D4H,09EH,0D2H,000H,09CH,0A1H,0CAH,0B8H + DB 0C8H,0C7H,0C2H,0C1H,0C3H,0C4H,0BAH,0DBH + ; + ; CTRL characters + ; +QKBDC: DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB NOKEY,05AH,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB 0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,NOKEY,NOKEY + DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + DB NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY,NOKEY + ; + ; Shift graphics + ; +QKBDGS: DB 0BFH,NOKEY,0CFH,0C9H,NOKEY,0B5H,04DH,0CDH + DB 035H,077H,0D7H,0B3H,0B7H,NOKEY,NOKEY,NOKEY + DB 07CH,070H,041H,031H,039H,0A6H,078H,0DDH + DB 03DH,05DH,06CH,056H,01DH,033H,0D5H,0B1H + DB 046H,06EH,0D9H,048H,074H,043H,04CH,073H + DB 03FH,036H,07EH,03BH,07AH,01EH,05FH,0A2H + DB 0D3H,09FH,0D1H,000H,09DH,0A3H,0D0H,0B9H + DB 0C6H,0C5H,0C2H,0C1H,0C3H,0C4H,0BBH,0BEH +FDUMP: + CALL FHLHEX ; address from + CALL @IC4DE ; + PUSH HL ; hide + CALL @HLHEX ; address kam + POP DE ; pull the address from where + JR C,J0D88 ; incorrect entry +J0D36: EX DE,HL ; DE ... end, HL ... beginning +J0D37: LD B,8 ; number of apartments per row + LD C,23 ; shifted HEXA and ASCII text + CALL @?NLHL ; address from the beginning of the line to the CRT +J0D3E: CALL @MHEX ; byte below (HL) + INC HL ; next byte + PUSH AF ; + LD A,(CURSOR) ; column + ADD A,C ; the cursor at points to ASCII + LD (CURSOR),A ; column + POP AF + CP SPACE ; gap? + JR NC,J0D51 + LD A,'.' ; flats P32 replace with a dot +J0D51: CALL @?ADCN ; to the display code + CALL @PRNTA ; and send + LD A,(CURSOR) + INC C ; the cursor returns + SUB C + LD (CURSOR),A ; and saves + DEC C ; edit cursor + DEC C + DEC C + PUSH HL + SBC HL,DE ; the end? + POP HL + JR Z,J0D85 ; yes, jump to the monitor + LD A,11111000B + LD (MKBOUT),A + NOP + LD A,(MKBDIN) + CP 11111110B ; suspension request? + JR NZ,J0D78 + CALL @?BLNK ; suspend listing +J0D78: DJNZ J0D3E ; another byte on the line +J0D7A: CALL @GETKD ; test suspended again + OR A + JR Z,J0D7A + CALL BRKEY + JR NZ,J0D37 ; there was no break, another line +J0D85: JP FPRMPT +J0D88: LD HL,160 + ADD HL,DE ; default end address + JR J0D36 ; and I continue + ; + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; + ; Wait for the beginning of the frame dimming pulse + ; +@?BLNK: + PUSH AF +J0DA7: LD A,(MPORTC) + RLCA + JR NC,J0DA7 ; wait for high +J0DAD: LD A,(MPORTC) + RLCA + JR C,J0DAD ; wait for low + POP AF + RET + ; + ; Saves the character at the cursor position in the VRAM, and executes + ; cursor right. When saving a character to the last column, + ; adjust line end attributes. + ; + ; input: A - character in the display code + ; +@AVRAM: + PUSH AF + PUSH BC + PUSH DE + PUSH HL +J0DB9: + CALL @?POINT ; cursor address + LD (HL),A ; save character + LD HL,(CURSOR) + LD A,L + CP 39 + JR NZ,J0DD0 ; we are not at the end of the line + CALL @ATBLN ; attributes + JR C,J0DD0 ; the current line is already ongoing + EX DE,HL + LD (HL),1 ; the next will be continued + INC HL + LD (HL),0 ; and no more +J0DD0: LD A,0C3H ; cursor right + JR J0DE0 ; • DPCT without saving the registry + ; + ; Query the set input mode + ; + ; output: A - 0CAH ... graphic mode setting character + ; Z = 1 ... graphically mod + ; 0 ... alphanumeric mod + ; +@?GMOD: + LD A,(CONMOD) + CP 1 + LD A,0CAH + RET + ; + ; Execution of control characters C0 - CF on CRT + ; All other codes are ignored + ; The meaning of the individual codes is described in + ; tableQ ADISP. + ; + ; input: A = control code C0-CF + ; +@?DPCT: + PUSH AF + PUSH BC + PUSH DE + PUSH HL +J0DE0: LD B,A ; control code i to B + AND 11110000B + CP 0C0H ; is it really control code? + JR NZ,EXIT1 ; no + XOR B ; character without upper four bits + RLCA ; * 2 + LD C,A ; index into the table + LD B,0 + LD HL,QADISP ; service address table + ADD HL,BC ; index table + LD E,(HL) ; service address to HL + INC HL + LD D,(HL) + LD HL,(CURSOR) ; cursor position to DE + EX DE,HL + JP (HL) ; sell control services + ; + ; Cursor o line niz + ; If it is already on the 24th line, it rolls + ; +CDOWN: + EX DE,HL + LD A,H + CP 24 ; the last line ? + JR Z,J0E23 ; yes, scroll + INC H ; o line dolu +EXITC: + LD (CURSOR),HL +EXIT1: + JP EXIT + ; + ; Cursor one line up + ; If it is already on the 0th line, nothing happens + ; +CUP: + EX DE,HL + LD A,H + OR A + JR Z,EXIT1 ; 0.line + DEC H ; on the previous line +J0E0B: JR EXITC + ; + ; Cursor one character to the right + ; +CRIGHT: + EX DE,HL + LD A,L + CP 39 ; last column? + JR NC,J0E16 ; Yes + INC L ; no, raise the column + JR EXITC ; return +J0E16: LD L,0 ; the column was the last + INC H ; on another line + LD A,H ; + CP 25 ; on the last line? + JR C,EXITC ; no, everything is OK + LD H,24 ; yes, he will stay there + LD (CURSOR),HL +J0E23: JR SCROLL ; and rolls off + ; + ; Cursor one character to the left + ; +CLEFT: + EX DE,HL + LD A,L + OR A + JR Z,J0E2D ; I'm at the beginning of the line + DEC L ; shrink + JR EXITC ; return +J0E2D: LD L,39 ; I'll be at the end of the line + DEC H ; and line vys + JP P,J0E0B ; return - nothing happened + LD H,0 ; column zero + LD (CURSOR),HL + JR EXIT1 + ; + ; Clear the screen + ; +CLEAR: + LD HL,QATBLN + LD B,27 + CALL @F0B ; delete row attributes + LD HL,ADRCRT ; reset VRAM data + CALL @FILL0 + LD A,IMPATB ; delete VRAM attributes + CALL @FILLA ; and then a home was made + ; + ; Cursor left up + ; +HOME: + LD HL,0 + JR EXITC + ; + DB 0,0,0,0,0,0,0,0 + ; + ; New line on CRT + ; +CRLF: + CALL @ATBLN + RRCA ; attribute of the next row? + JR NC,J0E16 ; is a continuation, skip it + LD L,0 ; Column 0 + INC H + CP 24 + JR Z,J0E6A ; end of screen, scroll + INC H + JR EXITC + ; +J0E6A: + LD (CURSOR),HL + ; + ; Scrolls the CRT up one logical line + ; +SCROLL: + LD BC,960 ; length + LD DE,ADRCRT + LD HL,ADRCRT+40 + PUSH BC + LDIR ; scrolled VRAM data + POP BC + PUSH DE + LD DE,ADRATB + LD HL,ADRATB+40 + LDIR ; scrolling VRAM attributes + LD B,40 + EX DE,HL + LD A,IMPATB + CALL @FAB ; deleting the last row of VRAM + POP HL + LD B,40 + CALL @F0B ; deleting the last row of VRAM + LD BC,26 + LD DE,QATBLN + LD HL,QATBLN+1 + LDIR ; line end attribute scrolling + LD (HL),0 + LD A,(QATBLN) ; attribute 0. radku + OR A + JR Z,EXIT ; not continued + LD HL,CURSOR+1 ; is continued, scrolls again + DEC (HL) ; cursor one line up + JR SCROLL ; and again + ; + ; CRT Service Address Table (C0-CF) + ; +QADISP: DW SCROLL ; C0 = Scroll + DW CDOWN ; C1 = Cursor down + DW CUP ; C2 = Cursor up + DW CRIGHT ; C3 = Cursor right + DW CLEFT ; C4 = Cursor left + DW HOME ; C5 = homeM + DW CLEAR ; C6 = clr + DW DELETE ; C7 = del + DW INSERT ; C8 = ins + DW ALPHA ; C9 = alph + DW GRAPH ; CA = graph + DW EXIT ; CB = not used + DW EXIT ; CC = not used + DW CRLF ; CD = cr + DW EXIT ; CE = not used + DW EXIT ; CF = not used + ; +J0ECA: SET 3,H ; it's a piece from INSERT + LD A,(HL) ; copies characters in VRAM-attributes + INC HL + LD (HL),A + DEC HL + RES 3,H ; and in VRAM data + LDD + LD A,C + OR B + JR NZ,J0ECA ; loop insert + EX DE,HL + LD (HL),0 ; under the cursor delete + SET 3,H + LD (HL),IMPATB ; and delete the attribute as well + JR EXIT + ; + ; Set alphanumeric mod + ; +ALPHA: + XOR A +J0EE2: LD (CONMOD),A + ; +EXIT: POP HL +J0EE6: POP DE + POP BC + POP AF + RET + ; + DB 0,0,0,0 + ; + ; Graphically sets the character, if it has already been set, the character + ; save to CRT + ; +GRAPH: + CALL @?GMOD ; it is set ? + JP Z,J0DB9 ; Yes + LD A,1 + JR J0EE2 ; jump to AVRAM without storage + ; + ; Delete the character to the left of the cursor + ; +DELETE: + EX DE,HL + LD A,H + OR L + JR Z,EXIT ; We're home + LD A,L + OR A + JR NZ,J0F0E ; the cursor is not at the beginning of the line + CALL @ATBLN ; the cursor is at the beginning of the line + JR C,J0F0E ; line is a continuation, normally lubricated + CALL @?POINT + DEC HL + LD (HL),0 ; to the end of the previous one + JR J0F33 + ; +J0F0E: CALL @ATBLN + RRCA ; the row attribute to CY + LD A,40 ; simple line + JR NC,J0F17 + RLCA ; continuation line +J0F17: SUB L ; the number of characters until the end of the line + LD B,A ; as a repeater + CALL @?POINT +J0F1C: ; shift B flat to the left + LD A,(HL) ; and VRAM data + DEC HL + LD (HL),A + INC HL + SET 3,H ; and in VRAM attributes + LD A,(HL) + DEC HL + LD (HL),A + RES 3,H + INC HL + INC HL + DJNZ J0F1C ; the last character has not been moved yet + DEC HL + LD (HL),0 ; delete the last character in the VRAM + SET 3,H ; also in VRAM attributes + LD HL,IMPATB ; HL MA APARTMENT IN BRACES +J0F33: LD A,0C4H ; cursor left + JP J0DE0 ; for hiding the registry? DPCT + ; + ; Insert a character in place of the cursor + ; +INSERT: + CALL @ATBLN + RRCA ; the row attribute to CY + LD L,39 ; simple length + LD A,L + JR NC,J0F42 ; + INC H ; line is double +J0F42: CALL @?ACUR ; line end address + PUSH HL + LD HL,(CURSOR) ; cursor position + JR NC,J0F4D + LD A,79 ; double line length +J0F4D: + SUB L ; the character remains until the end of the line + LD B,0 + LD C,A ; BC is the number of characters to the end of the line + POP DE ; reset line end address + JR Z,EXIT ; we are on the last character + LD A,(DE) ; last character + OR A + JR NZ,EXIT ; it is not a space, INSERT cannot + LD H,D + LD L,E + DEC HL ; penultimate address to HL + JP J0ECA + ; + ; SAVE monitor display + ; +FSAVE: + CALL FHLHEX ; enter the address in the HL + LD (BEGIN),HL ; this will be the boot address + LD B,H ; and will also be in BC + LD C,L + CALL @IC4DE ; to another address + CALL FHLHEX ; I'm with her + SBC HL,BC ; it is the end address + INC HL + LD (FSIZE),HL ; to the header + CALL @IC4DE ; and one more address + CALL FHLHEX + LD (ENTRY),HL ; start address + CALL @IFNL? ; novy line + LD DE,SFNAME ; query file name + RST 18H + CALL FGETL ; read the file name + CALL @IC4DE ; DE = DE + 8 + CALL @IC4DE + LD HL,FNAME ; address in the file name header +J0F8E: INC DE ; copy the name to the header + LD A,(DE) + LD (HL),A + INC HL + CP CR ; we end when there is CR + JR NZ,J0F8E + LD A,1 ; type is always 1 = ORDER NO + LD (HEAD),A + CALL WHEAD ; write the header + JP C,FCMTER ; error + CALL WDATA ; record that + JP C,FCMTER ; error + CALL @IFNL? + LD DE,MSGOK ; Write the message OKQ + RST 18H + JP FPRMPT ; to the monitor + ; + ; Return the cursor address to the VRAM + ; + ; output: HL = cursor address + ; +@?POINT: + LD HL,(CURSOR) +@?ACUR: ; this input assumes a position in HL + PUSH AF + PUSH BC + PUSH DE + PUSH HL + POP BC ; position is in BC + LD DE,40 ; length of work + LD HL,ADRCRT-40 ; before the CRT address +J0FBF: ADD HL,DE ; * 40 + DEC B + JP P,J0FBF + LD B,0 + ADD HL,BC ; add a column + POP DE + POP BC + POP AF + RET + ; +FVERIF: ; File verification + CALL VERIF ; perform verification + JP C,FCMTER ; error or break + LD DE,MSGOK ; List OK! + RST 18H + JP FPRMPT ; to the monitor + ; + ; Zero memory full ( see @ FAB ) + ; +@F0B: XOR A + JR @FAB + ; + ; Full FF memory ( see @ FAB ) + ; +@FFFB: LD A,0FFH + ; + ; Full memory constant + ; + ; Input: HL - address + ; A - the value by which it is fulfilled + ; B - number of apartments + ; + ; Output: HL = HL + B + ; A = constant by which it was filled + ; +@FAB: LD (HL),A + INC HL + DJNZ @FAB + RET + ; + ; Waiting for 100 zeros on CMT (think bit zeros) + ; + ; output: CY = 1 ... break + ; CY = 0 ... zeros found + ; +@RINTR: + PUSH BC + PUSH DE + PUSH HL + LD BC,MKBDIN ; registers for W0TO1 + LD DE,MPORTC +J0FEB: LD H,100 +J0FED: CALL W0TO1 ; wait for the leading edge + JR C,J0FFD ; break + CALL @D331 ; waiting for READ POINT + LD A,(DE) ; honor 8255 gate C + AND 00100000B ; test read CMT bit + JR NZ,J0FEB ; the one does not have to be there + DEC H ; a mame dalsi zero + JR NZ,J0FED ; there are not 100 of them yet +J0FFD: JP POPX2 + ; diff --git a/software/asm/MZ800_9Z_504M.asm b/software/asm/MZ800_9Z_504M.asm new file mode 100644 index 0000000..b23dd81 --- /dev/null +++ b/software/asm/MZ800_9Z_504M.asm @@ -0,0 +1,3067 @@ + ; + ; + ; SHARPMZ - 821 + ; (ROM contents, upper monitor E000-F3FF) + ; + ; + ; Input / Output address + + + INCLUDE "Macros.asm" + + + ; + ; Printer interface +PCPR: EQU 0FCH ; Z80 / PIO +PLPT: EQU PCPR+3 ; printer data output +PLPTS: EQU PCPR+2 ; printer strobe +PLPTI: EQU PCPR+1 ; printer data port inic +PLPTSI: EQU PCPR+0 ; printer strobe port inic + ; Program sound generator +PPSG: EQU 0F2H ; Prog. Sound Gen. + ; Joystick registers +PJ1: EQU 0F1H ; joystick-2 input port +PJ0: EQU 0F0H ; joystick-1 input port + ; Pallet write +PPAL: EQU 0F0H ; pallet write + ; Memory managerment ports OUT +PMMC6: EQU 0E6H ; condition from hill protection +PMMC5: EQU 0E5H ; protect the hill +PMMC4: EQU 0E4H ; maximum neRAM as far as possible +PMMC3: EQU 0E3H ; ROM up +PMMC2: EQU 0E2H ; ROM down + ; Memory managerment ports OUT / IN +PMMC1: EQU 0E1H ; DRAM up / VRAM pryc +PMMC0: EQU 0E0H ; DRAM up / VRAM + ; Folppy disk +PFD: EQU 0D8H +PFDSIZ: EQU PFD+5 ; floppy side settings +PFDMOT: EQU PFD+4 ; drive on / off +PFDDAT: EQU PFD+3 ; register that +PFDSEC: EQU PFD+2 ; sector register +PFDTRK: EQU PFD+1 ; track register +PFDCTR: EQU PFD+0 ; driving word + ; 8253 I / O. mapped. - interupt, clock, etc. +P8253: EQU 0D4H ; 8253 I / O. Mapped +PCTCC: EQU P8253+3 ; control word 8253 +PCTC2: EQU P8253+2 ; counter 2 +PCTC1: EQU P8253+1 ; counter 1 +PCTC0: EQU P8253+0 ; counter 0 + ; 8255 I / O mapped - keyboard, joystick, CMT +P8255: EQU 0D0H +PCWR55: EQU P8255+3 ; control word 8255 +PPORTC: EQU P8255+2 ; port C - CMT and control +PKBDIN: EQU P8255+1 ; keyboard input +PKBOUT: EQU P8255+0 ; keyboard strobe + ; GDG I / O ports +PCRTC: EQU 0CFH ; CRTC register +PDMD: EQU 0CEH ; display mod register +PRF: EQU 0CDH ; read format register +PWF: EQU 0CCH ; write format register + ; + ; Memory mapping + ; +MGATE0: EQU 0E008H ; disable / enable melody + ; 8253 mem. mapped - Interupt, clock +M8253: EQU 0E004H ; 8253 Mem. Mapped +MCTCC: EQU M8253+3 ; control word 8253 +MCTC2: EQU M8253+2 ; counter 2 +MCTC1: EQU M8253+1 ; counter 1 +MCTC0: EQU M8253+0 ; counter 0 + ; 8255 mem. mapped - keyboard, joystick, CMT +M8255: EQU 0E000H +MCWR55: EQU M8255+3 ; control word 8255 +MPORTC: EQU M8255+2 ; port C - CMT and control +MKBDIN: EQU M8255+1 ; keyboard input +MKBOUT: EQU M8255+0 ; keyboard strobe + ; + ; definition of ASCII constants +CR: EQU 0DH +SPACE: EQU 20H +ESC: EQU 1BH +CLS: EQU 16H +CRD: EQU 0CDH + ; definition of display addresses +ADRCRT: EQU 0D000H ; address MZ-700 VRAM +ADRATB: EQU 0D800H ; the address of the CRS attribute +IMPATB: EQU 71H ; default display attribute + ; + ORG 0E000H + ; + ; Ports D0-D7 are mapped here in MZ-700 mode + ; + DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH + DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH + ;---------------------------------------------------- + ; + ; QUICKDISK + ; + ;---------------------------------------------------- +@QDISK: + LD A,5 + LD (M1145),A +JE015: + DI + CALL JE06A + RET NC + PUSH AF + CP 28H + JR Z,JE068 + CALL JE2E8 + LD A,(M1130) + CP 4 + JR NZ,JE045 + LD A,(M1141) + OR A + JR Z,JE045 + XOR A + LD (M1141),A + LD A,(M1142) + PUSH HL + LD (OLDSP),SP + POP HL + DI + CALL JE268 + JR C,JE062 + CALL JE2E8 +JE045: + CP 3 + JR NZ,JE04D + LD HL,113DH + DEC (HL) +JE04D: + POP AF + PUSH AF + CP 29H + JR NZ,JE062 + LD HL,1145H + DEC (HL) + JR Z,JE062 + POP AF + LD A,(M1140) + LD (M113F),A + JR JE015 + ; +JE062: + CALL JE1DB + CALL JE083 +JE068: + POP AF + RET + ; +JE06A: + LD (OLDSP),SP + LD A,(M1130) + DEC A + JR Z,JE08A + DEC A + JR Z,JE090 + DEC A + JR Z,JE0DA + DEC A + JP Z,JE14E + DEC A + JR Z,JE083 + JR JE0D3 + ; +JE083: + PUSH AF + XOR A + LD (M113D),A + POP AF + RET + ; +JE08A: + LD A,(M1131) + JP JE23C + ; +JE090: + XOR A + CALL JE268 + CALL JE365 + LD BC,0EFFFH + LD A,0AAH +JE09C: + CPL + LD D,A + CALL JE3DB + DEC BC + LD A,B + OR C + JR Z,JE0A9 + LD A,D + JR JE09C + ; +JE0A9: + CALL JE3B2 + CALL JE2E8 + CALL JE29B + LD A,(M1143) + DEC A + JR NZ,JE0D6 + CALL JE2FD + LD BC,0EFFFH + LD E,55H +JE0C0: + CP E + JR NZ,JE0D6 + DEC BC + LD A,B + OR C + JR Z,JE0D0 + LD A,E + CPL + LD E,A + CALL JE3F0 + JR JE0C0 + ; +JE0D0: + CALL JE3C3 +JE0D3: + JP JE2E8 + ; +JE0D6: + LD A,29H + SCF + RET + ; +JE0DA: + LD A,(M1144) + OR A + CALL Z,JE29B + CALL JE114 + RET C + CALL JE435 + CALL JE3F0 + LD C,A + CALL JE3F0 + LD B,A + OR C + JP Z,JE1E5 + LD HL,(M1134) + SBC HL,BC + JP C,JE1E5 + LD HL,(M1132) +JE0FF: + CALL JE3F0 + LD (HL),A + INC HL + DEC BC + LD A,B + OR C + JR NZ,JE0FF + CALL JE3C3 + LD A,(M1131) + BIT 0,A + JR NZ,JE0D3 + RET + ; +JE114: + LD HL,1143H + DEC (HL) + JR Z,JE14A + CALL JE2FD + LD C,A + LD A,(M113D) + LD HL,113EH + CP (HL) + JR NZ,JE147 + INC A + LD (M113D),A + LD (HL),A + LD A,(M1131) + XOR C + RRA + RET NC +JE132: + CALL JE3F0 + LD C,A + CALL JE3F0 + LD B,A +JE13A: + CALL JE3F0 + DEC BC + LD A,B + OR C + JR NZ,JE13A + CALL JE3C3 + JR JE114 + ; +JE147: + INC (HL) + JR JE132 + ; +JE14A: + LD A,28H + SCF + RET + ; +JE14E: + LD A,(M113F) + LD (M1140),A + LD A,(M1144) + OR A + JR NZ,JE171 + CALL JE29B + LD A,(M113F) + LD HL,1143H + ADD A,(HL) + LD (M1143),A + INC A + LD (M113D),A + CALL JE114 + JP NC,JE1E5 +JE171: + LD A,(M1131) + LD B,A + AND 1 + JR NZ,JE185 + LD DE,1132H + LD A,B + RES 2,A + CALL JE1ED + CALL JE435 +JE185: + LD DE,1136H + LD A,(M1131) + SET 0,A + CALL JE1ED + CALL JE2E8 + CALL JE435 + LD A,(M1131) + AND 4 + JR Z,JE1E8 + LD A,(M1142) + LD HL,113FH + ADD A,(HL) + CALL JE268 + LD A,1 + LD (M1141),A +JE1AC: + LD A,(M1142) + LD HL,1140H + ADD A,(HL) + INC A + LD (M1143),A + INC A + LD (M113D),A + CALL JE114 + JR NC,JE1E5 + LD A,(M1131) + AND 1 + JR NZ,JE1CE + LD DE,1132H + CALL JE21B + RET C +JE1CE: + LD DE,1136H + CALL JE21B + RET C + LD A,(M1141) + OR A + JR Z,JE1E2 +JE1DB: + XOR A + LD (M113F),A + LD (M1141),A +JE1E2: + JP JE2E8 + ; +JE1E5: + JP JE0D6 + ; +JE1E8: + CALL JE29B + JR JE1AC + ; +JE1ED: + PUSH AF + LD HL,113FH + INC (HL) + CALL JE365 + POP AF + CALL JE3DB + CALL JE211 + LD A,C + CALL JE3DB + LD A,B + CALL JE3DB +JE204: + LD A,(HL) + CALL JE3DB + INC HL + DEC BC + LD A,B + OR C + JR NZ,JE204 + JP JE3B2 + ; +JE211: + EX DE,HL + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD C,(HL) + INC HL + LD B,(HL) + EX DE,HL + RET + ; +JE21B: + CALL JE2FD + CALL JE211 + CALL JE3F0 + CP C + JR NZ,JE1E5 + CALL JE3F0 + CP B + JR NZ,JE1E5 +JE22D: + CALL JE3F0 + CP (HL) + JR NZ,JE1E5 + INC HL + DEC BC + LD A,B + OR C + JR NZ,JE22D + JP JE3C3 + ; +JE23C: + LD B,A + LD A,2 + OUT (0F7H),A + LD A,81H + OUT (0F7H),A + LD A,2 + OUT (0F7H),A + IN A,(0F7H) + AND 81H + CP 81H + JP NZ,JE406 + LD A,10H + OUT (0F6H),A + IN A,(0F6H) + LD C,A + AND 8 + JP Z,JE406 + LD A,B + OR A + RET Z + LD A,C + AND 20H + RET NZ + JP JE403 + ; +JE268: + PUSH AF + LD HL,0E42CH + LD B,9 + CALL JE2D8 +JE271: + LD A,10H + OUT (0F6H),A + IN A,(0F6H) + AND 8 + JP Z,JE406 + LD A,10H + OUT (0F7H),A + IN A,(0F7H) + AND 8 + JR Z,JE271 + LD BC,0E9H + CALL @944BC + CALL JE39A + CALL JE37E + POP AF + CALL JE3DB + CALL JE3B2 + JR JE2CE + ; +JE29B: + LD HL,0E421H + LD B,0BH + CALL JE2D8 +JE2A3: + LD A,10H + OUT (0F6H),A + IN A,(0F6H) + AND 8 + JP Z,JE406 + CALL JE435 + LD A,10H + OUT (0F7H),A + IN A,(0F7H) + AND 8 + JR Z,JE2A3 + LD BC,0E9H + CALL @944BC + CALL JE313 + LD (M1142),A + INC A + LD (M1143),A + CALL JE3C3 +JE2CE: + LD HL,1147H + SET 3,(HL) + XOR A + LD (M113E),A + RET + ; +JE2D8: + LD C,0F6H + OTIR + LD A,5 + LD (M1144),A + OUT (0F7H),A + LD A,80H + OUT (0F7H),A + RET + ; +JE2E8: + PUSH AF + LD A,5 + OUT (0F6H),A + LD A,60H + OUT (0F6H),A + LD A,5 + OUT (0F7H),A + XOR A + LD (M1144),A + OUT (0F7H),A + POP AF + RET + ; +JE2FD: + LD A,58H + LD B,0BH + LD HL,0E421H + CALL JE3A3 + LD HL,1147H + BIT 3,(HL) + LD BC,3 + JR Z,JE316 + RES 3,(HL) +JE313: + LD BC,0A0H +JE316: + CALL @944BC + LD A,5 + OUT (0F7H),A + LD A,82H + OUT (0F7H),A + LD A,3 + OUT (0F6H),A + LD A,0D3H + OUT (0F6H),A + LD BC,2CC0H +JE32C: + LD A,10H + OUT (0F6H),A + IN A,(0F6H) + AND 10H + JR Z,JE33D + DEC BC + LD A,B + OR C + JR NZ,JE32C + JR JE354 + ; +JE33D: + LD A,3 + OUT (0F6H),A + LD A,0C3H + OUT (0F6H),A + LD B,9FH +JE347: + LD A,10H + OUT (0F6H),A + IN A,(0F6H) + AND 1 + JR NZ,JE357 + DEC B + JR NZ,JE347 +JE354: + JP JE40C + ; +JE357: + LD A,3 + OUT (0F6H),A + LD A,0C9H + OUT (0F6H),A + CALL JE3F0 + JP JE3F0 + ; +JE365: + LD A,98H + LD B,9 + LD HL,0E42CH + CALL JE3A3 + CALL JE39A + LD HL,1147H + BIT 3,(HL) + LD BC,1DH + JR Z,JE381 + RES 3,(HL) +JE37E: + LD BC,140H +JE381: + CALL @944BC + LD A,5 + OUT (0F6H),A + LD A,0EFH + OUT (0F6H),A + LD BC,1 + CALL @944BC + LD A,0A5H + CALL JE3DB + JP JF380 + ; +JE39A: + LD A,5 + OUT (0F6H),A + LD A,0FFH + OUT (0F6H),A + RET + ; +JE3A3: + LD C,0F6H + OUT (C),A + LD A,5 + OUT (0F7H),A + LD A,80H + OUT (0F7H),A + OTIR + RET + ; +JE3B2: + LD BC,1 + CALL @944BC + LD A,10H + OUT (0F7H),A + IN A,(0F7H) + AND 8 + RET NZ + JR JE409 + ; +JE3C3: + LD B,3 +JE3C5: + CALL JE3F0 + DJNZ JE3C5 +JE3CA: + IN A,(0F6H) + RRCA + JR NC,JE3CA + LD A,1 + OUT (0F6H),A + IN A,(0F6H) + AND 40H + JR NZ,JE400 + OR A + RET + ; +JE3DB: + PUSH AF +JE3DC: + IN A,(0F6H) + AND 4 + JR Z,JE3DC + POP AF + OUT (0F4H),A +JE3E5: + LD A,10H + OUT (0F6H),A + IN A,(0F6H) + AND 8 + JR Z,JE406 + RET + ; +JE3F0: + CALL JE3E5 + IN A,(0F6H) + RLCA + JR C,JE400 + RRCA + RRCA + JR NC,JE3F0 + IN A,(0F4H) + OR A + RET + ; +JE400: + LD A,29H + LD HL,2E3EH +JE403: EQU 0E403H + LD HL,323EH +JE406: EQU 0E406H + LD HL,353EH +JE409: EQU 0E409H + LD HL,363EH +JE40C: EQU 0E40CH + LD SP,(OLDSP) + SCF + RET + ; +@944BC: + PUSH AF +JE415: + LD A,96H +JE417: + DEC A + JR NZ,JE417 + DEC BC + LD A,B + OR C + JR NZ,JE415 + POP AF + RET + ; + LD E,B + INC B + DJNZ JE42A + INC B + INC BC + RET NC + LD B,16H +JE42A: + RLCA + LD D,98H + INC B + DJNZ JE436 + LD D,7 + LD D,5 + LD L,L +JE435: + LD A,0E8H +JE436: EQU 0E436H + LD (MKBOUT),A + NOP + LD A,(MKBDIN) + AND 81H + RET NZ + CALL JE1DB + LD SP,(OLDSP) + SCF + RET + ;---------------------------------------------------- + ; + ; FLOPPYDISK + ; + ;---------------------------------------------------- + ; + ; Most subroutines use error returns, + ; for this case it is necessary to set the return + ; address to FDARET and be aware that the CAP will change + ; + ; + ; Read the program from FD and run + ; The program can pass control back to the RET instruction. + ; The program name must start with IPLPRO, otherwise it will be executed + ; error return FDERR1. Only the rest is shown on the display + ; names. + ; + ; nothing: everything + ; +@FDBOOT: ; floppy disc BOOT + EX (SP),HL ; + LD (FDARET),HL ; return address + CALL @???FD ; fdc? + JP NZ,FDERR0 + LD DE,FDCB ; parameter block + LD HL,TFDTAB ; initial values + LD BC,11 ; 11 Byte + LDIR ; move ... + CALL @FDDESL ; deselect + LD IX,FDCB ; parameters + CALL @FDREAD ; read ... + LD HL,FDHEAD ; compared to + LD DE,TIPLPR ; 03 "IPLPRO" + LD B,7 ; +JE471: LD C,(HL) ; + LD A,(DE) ; + CP C ; + JP NZ,FDERR1 ; IPLPRO not found + INC HL ; + INC DE ; + DJNZ JE471 ; comparison loop + LD DE,IPLM0 ; "IPL IS LOADING" + RST 18H ; + LD DE,FDHEAD+7 ; filename, the other half + RST 18H ; + LD HL,MGBASE ; + LD (IX+005H),L ; boot address of the program + LD (IX+006H),H ; + LD HL,(FDHEAD+14H) ; + LD (IX+003H),L ; block length + LD (IX+004H),H ; + LD HL,(FDHEAD+1EH) ; + LD (IX+001H),L ; sector number calculated + LD (IX+002H),H ; from the beginning of the block + CALL @FDREAD ; honor data + CALL @FDDESL ; disconnect disks + LD BC,200H ; starts from FD + EXX + LD HL,FDHEAD+14H ; address to the header file + JP QGOPGM + ; + ; Error correction + ; +FDERR1: + CALL @FDDESL ; disconnect disks + LD DE,ERRM1 ; FD: not master + JR FDCERR +FDERR3: + CP 32H ; diskette request? + JR NZ,JE4BF ; no, it's a mistake +FDERR0: ; request to turn on the floppy disk + LD DE,IPLM3 ; Make ready FD + JR FDCERR +JE4BF: LD DE,ERRM0 ; FD: loading error +FDCERR: LD SP,NEWSP-2 ; almost initialize the clip + LD HL,(FDARET) ; return address + EX (SP),HL ; to the clip instead of something + RET + ; + ; The name of the file with the FD loader + ; +TIPLPR: DB 03H ; type BSD + DB "IPLPRO" ; the name of the bootloader + ; + ; Sample FD disk table, used by the FDBOOT routine + ; is copied to RAM + ; +TFDTAB: DB 0 ; disc number (0-3) + DW 00 ; block number from the beginning of the disc + DW 256 ; the length of the read block + DW FDHEAD ; boot address + DB 0 ; current rate + DB 0 ; current sector + DB 0 ; initial rate + DB 0 ; initial sector + ; + ; Select a disk and perform a restore if selected + ; first + ; + ; nothing: what is possible + ; +@FDSEL: ; Drive selct & restore if desired + LD A,(FDON?) + RRCA ; engine ON? + CALL NC,@FDON ; NO =M turn ON + LD A,(IX+000H) ; disk number + OR 10000100B ; pricist prikaz + OUT (PFDMOT),A ; select disk + XOR A + LD (FDCMD),A ; disk selected + CALL @D60MS ; I'd rather wait + LD HL,0 +JE4F4: DEC HL + LD A,H + OR L + JR Z,JE512 ; TO expired + IN A,(PFDCTR) ; status read + CPL + RLCA + JR C,JE4F4 ; is waiting for the FDC + LD C,(IX+000H) ; disk number + LD HL,TFDRES + LD B,0 + ADD HL,BC ; index table + BIT 0,(HL) ; connected disks + JR NZ,JE511 ; the disk has been connected + CALL @FDTR0 ; restore + SET 0,(HL) ; but come to restore no +JE511: RET +JE512: LD A,32H ; TO expired + JP FDERR2 + ; + ; Turn on the floppy disk motor + ; +@FDON: + LD A,80H + OUT (PFDMOT),A ; start the engine + LD B,16 +JE51D: CALL @D60MS ; delay approx. 960 MS + DJNZ JE51D + LD A,1 + LD (FDON?),A ; on flag + RET + ; + ; Search for the drive of the selected track + ; +@FDSEEK: + LD A,1BH ; track search display + CALL @FDCOPE + AND 10011001B ; edit status + RET + ; + ; Disconnected floppy disks + ; +@FDDESL: + PUSH AF + CALL @D1200 + XOR A + OUT (PFDMOT),A ; disconnect display + LD (TFDRES),A ; reset all flags + LD (TFDRES+1),A ; for all disks before work + LD (TFDRES+2),A ; will have to perform FDTR0 + LD (TFDRES+3),A + LD (FDON?),A ; and also turn off the engine + POP AF + RET + ; + ; Restore floppy (to 0th track) + ; +@FDTR0: + LD A,0BH ; RESTORE display + CALL @FDCOPE ; exhibit + AND 10000101B ; mask status + XOR 00000100B + RET Z ; everything OK + JP FDERR4 + ; + ; Send the display to the FD controller, also save the display and status + ; to the appropriate variables + ; + ; input: A = display for FD + ; output: A = status + ; +@FDCOPE: + LD (FDCMD),A ; save your display + CPL + OUT (PFDCTR),A ; to radice + CALL @FDWT1 ; wait for not busy + CALL @D60MS ; delay + IN A,(PFDCTR) ; status + CPL + LD (FDSTAT),A ; impose + RET + ; + ; Wait for FDC ready + ; if it doesn't, end with an error + ; + ; nici: AF + ; +@FDWT1: + PUSH DE + PUSH HL + CALL @FDREPC ; delay 125 microseconds +JE56D: LD HL,0 ; E = 7 ... number of repetitions +JE570: DEC HL + LD A,H + OR L + JR Z,JE57D ; IT has expired + IN A,(PFDCTR) ; status + RRCA + JR NC,JE570 ; you are not ready + POP HL ; FDC ready, all right + POP DE + RET +JE57D: DEC E + JR NZ,JE56D +JE580: LD A,29H ; error 29H, disk does not boot + POP HL + POP DE + JP FDERR2 + ; + ; Wait for the FDC to be busy, + ; if it doesn't finish, it ends with an error + ; + ; nici: AF + ; +@FDWT2: + PUSH DE + PUSH HL + CALL @FDREPC ; delay, E = 7 +JE58C: LD HL,0 +JE58F: DEC HL + LD A,H + OR L + JR Z,JE59C + IN A,(PFDCTR) ; status + RRCA + JR C,JE58F ; still ready + POP HL + POP DE + RET +JE59C: DEC E ; it is still necessary to wait + JR NZ,JE58C + JR JE580 ; end, error ERR 29H + ; + ; Delay 125 microseconds and 7 -M E + ; +@FDREPC: + CALL @D125 ; wait + LD E,7 ; that's the length of the next wait + RET + ; + ; Reads data from a floppy disk + ; +@FDREAD: + CALL @FDTR? ; calculate the footprint and the sector + CALL @FDPREP ; prepare disk and registers +JE5AD: CALL @FDTR ; set the track + CALL @FDSEEK ; look for her physically + JP NZ,FDERR2 ; failed + CALL @FDSEC ; set sector + DI ; do not interrupt, therefore + LD A,94H ; allow interruption + CALL FDSTRT ; start reading the sector +JE5BF: LD B,0 ; 256 apartments +JE5C1: IN A,(PFDCTR) ; status + RRCA + JR C,JE5E0 ; error + RRCA + JR C,JE5C1 ; not ready + INI ; precist byte + JR NZ,JE5C1 ; you are reading more + INC (IX+008H) ; read everything, another sector + LD A,(IX+008H) + CP 17 + JR Z,JE5DC ; go to the next track + DEC D + JR NZ,JE5BF ; honor another sector + JR JE5DD +JE5DC: DEC D +JE5DD: CALL @FDSTOP ; stop FD +JE5E0: NOP + IN A,(PFDCTR) ; status + CPL + LD (FDSTAT),A + AND 0FFH + JR NZ,FDERR4 + CALL @FDNEXT ; dalsi stop + JP Z,JE5F6 ; end of disc + LD A,(IX+007H) ; it should do FDPREP + JR JE5AD ; and cte se dal +JE5F6: LD A,80H ; end of disc + OUT (PFDMOT),A + RET + ; + ; Prepare a floppy disk and file parameters to the registry + ; + ; output: D = number of file sectors + ; HL = boot address + ; A = rate + ; +@FDPREP: + CALL @FDSEL ; select disc + LD D,(IX+004H) + LD A,(IX+003H) + OR A ; length MOD 256 + JR Z,JE608 ; it is a multiple of 256 + INC D ; this short is also read +JE608: LD A,(IX+00AH) ; in D is now the number of sectors + LD (IX+008H),A ; copy initial number + LD A,(IX+009H) ; tracks to the current + LD (IX+007H),A ; + LD L,(IX+005H) ; boot address + LD H,(IX+006H) + RET + ; + ; Set the physical track and side of the floppy, odd tracks + ; they are on one side and the barrel on the other side + ; + ; input: A = logical track number + ; nici: AF + ; +@FDTR: + SRL A ; rate / 2 + CPL + OUT (PFDDAT),A ; set a track + JR NC,JE626 + LD A,1 ; licha stopa + JR JE627 +JE626: XOR A ; suda stopa +JE627: CPL + OUT (PFDSIZ),A ; set page + RET + ; + ; Set the track and sector according to the data in the FDCB + ; + ; output: C = PFDDAT + ; A = sector + ; +@FDSEC: + LD C,PFDDAT ; THIS IS NOT NEEDED + LD A,(IX+007H) ; track + SRL A ; / 2, on the side of the coffin + CPL + OUT (PFDTRK),A ; set + LD A,(IX+008H) ; sector + CPL + OUT (PFDSEC),A ; set + RET + ; + ; Parameters in FDCB on the next track + ; + ; output: A = D ... number of sectors to transmit + ; F ....... set according to A and therefore also D + ; +@FDNEXT: + LD A,(IX+008H) ; sector + CP 17 ; is the last one? + JR NZ,JE64B ; no + LD A,1 ; Sector 1 + LD (IX+008H),A + INC (IX+007H) ; another footprint +JE64B: LD A,D ; you will transfer me + OR A + RET + ; + ; Show on FD + ; +FDSTRT: + LD (FDCMD),A ; save the display + CPL + OUT (PFDCTR),A ; send + CALL @FDWT2 ; wait for it to work + RET + ; + ; Stop FD + ; + ; nici: AF + ; +@FDSTOP: + LD A,PFDCTR ; stop display + CPL + OUT (PFDCTR),A ; stop + CALL @FDWT1 ; wait for it to stop + RET + ; + ; Errors when working with FD + ; +FDERR4: + LD A,(FDCMD) ; last view + CP 0BH + JR Z,JE683 + CP 1BH + JR Z,JE683 + CP 0F4H + JR Z,JE683 + LD A,(FDSTAT) ; status + BIT 7,A + JR NZ,JE68E + BIT 6,A + JR NZ,JE68A + BIT 4,A + LD A,36H + JR NZ,FDERR2 + JR JE68A +JE683: LD A,(FDSTAT) + BIT 7,A + JR NZ,JE68E +JE68A: LD A,29H + JR FDERR2 +JE68E: LD A,32H +FDERR2: CALL @FDDESL + JP FDERR3 + ; + ; The computed trace number from the sector address on the FDCB (1) a + ; FDCB (2). The result will be FDCB (9) = foot + ; FDCB (10) = sector + ; output: H = B = initial track of the file + ; L = initial sector of the file + ; DE = 16 + ; A = 0 + ; +@FDTR?: + LD B,0 + LD DE,16 ; sector on track + LD L,(IX+001H) ; sector address + LD H,(IX+002H) + XOR A ; +JE6A2: SBC HL,DE ; about 16 sectors + JR C,JE6A9 + INC B ; means 1 foot more + JR JE6A2 ; and again +JE6A9: ADD HL,DE ; sector number remains in L + LD H,B ; the track number will be in H + INC L ; sectors are counted from 1 + LD (IX+009H),H ; save to FDCB + LD (IX+00AH),L + RET + ; + ; delay approx. 125 microseconds + ; +@D125: + PUSH DE + LD DE,0FH + JR D60MS1 + ; + ; delay approx. 1.2 milliseconds + ; +@D1200: + PUSH DE + LD DE,0A0H + JR D60MS1 + ; + ; Delay approx. 60 milliseconds + ; +@D60MS: + PUSH DE + LD DE,2026H +D60MS1: DEC DE + LD A,E + OR D + JR NZ,D60MS1 + POP DE + RET + ;---------------------------------------------------- + ; + ; RAMDISK + ; + ;---------------------------------------------------- + ; + ; Load the program from the house + ; +QEB: + CALL @RDLOAD ; honor program from RD + JP NZ,CMTERR ; error +QGORD: + LD BC,0 ; and run it + EXX + LD HL,FSIZE ; GOPGM needs it + JP QGOPGM + ; + ; Read the program from the Ram disk + ; + ; input: C = I / O address + ; input: Z = 1 ... program read OK + ; 0 ... checksum error + ; +@RDLOAD: + CALL JE729 ; check the CRC on the RD + RET NZ + IN A,(C) + INC C ; entry address + LD HL,FSIZE + LD B,9 + INIR ; piece of head here + LD DE,(FSIZE) + LD HL,MGBASE + LD A,E + OR A ; length MOD 256 + JR Z,JE6F6 ; it's in whole blocks + LD B,A +JE6F4: INIR +JE6F6: LD B,0 + DEC D + JP P,JE6F4 ; for each block + LD DE,MGBASE + LD BC,(FSIZE) + CALL @RDCRC ; counted CRC + LD DE,(RDCRC) + OR A + SBC HL,DE ; and compare with read + RET + ; + ; Count checksum + ; + ; input: BC = block length in bytes + ; DE = block address + ; + ; output: BC = 8 + ; DE = DE ' + ; HL = calculated CRC + ; BC '= 0 + ; DE '= address after the data block + ; HL '= HL + ; A = 0 + ; +@RDCRC: + EXX + LD HL,0 ; they will feel the same here + LD C,8 ; byte ma 8 bit + EXX +JE715: LD A,B + OR C + JR Z,JE727 ; everything is already calculated + LD A,(DE) ; another byte from the file + EXX + LD B,C ; it's 8 +JE71C: RLCA + JR NC,JE720 + INC HL ; it's one +JE720: DJNZ JE71C ; 8 times + EXX + INC DE ; on the next byte + DEC BC ; and the length is shortened + JR JE715 ; repeat +JE727: EXX + RET + ; + ; Check the CRC header on the RD, read from the beginning of the RD + ; 8 bytes, 9th byte is considered the number of units + ; + ; input: C = I / O port + ; output: Z = 1 ... CRC agrees + ; 0 ... checksum error + ; A = read CRC from RD + ; D = calculated CRC + ; B = 0 + ; +JE729: + IN A,(C) ; pointer to the beginning + LD B,8 + LD D,0 + INC C ; cteci port +JE730: IN A,(C) + PUSH BC + LD B,8 +JE735: RLCA + JR NC,JE739 + INC D ; we feel one +JE739: DJNZ JE735 ; 8 times + LD A,D + POP BC + LD D,A + DJNZ JE730 ; 8 times + IN A,(C) ; cti CRC + DEC C ; turn control port + CP D ; compare with CRC calculated + RET + ; + ; Read the program from the CMT and save it to the RAM disk + ; +QES: + LD DE,SRCPRG ; Ramcard prog. + CALL IFNL? + RST 18H + CALL IFNL? + LD DE,SMASTS ; Master tape set + RST 18H + CALL IFNL? + CALL @RHEAD ; header from CMT + JR C,JE769 ; failed + LD DE,MSGLD ; Loading + CALL IFNL? + RST 18H + LD DE,FNAME ; listing file name + RST 18H + CALL @RDATA ; and honor data from CMT +JE769: JP C,CMTERR ; CMT error + IN A,(C) ; at the beginning of the RAM disk + LD (RDADR),BC ; save the IIO address of the RD + LD DE,(BEGIN) + LD BC,(FSIZE) + PUSH DE + PUSH BC + CALL @RDCRC ; counted CRC + LD (RDCRC),HL ; save to header + LD HL,FSIZE + LD BC,(RDADR) ; restore I / O address + LD B,8 + INC C + INC C ; data output port + PUSH HL + PUSH BC ; 8 byte headers = + OTIR ; length, address, start, CRC + POP BC ; B = 8 C = I / O + POP HL + PUSH DE + LD D,0 ; calculate the CRC header +JE796: PUSH BC + LD B,8 + LD A,(HL) +JE79A: RLCA + JR NC,JE79E + INC D ; another one found +JE79E: DJNZ JE79A ; 8 times + INC HL + POP BC + DJNZ JE796 ; 8 times + LD A,D + POP DE + OUT (C),A ; CRC to RD + POP DE ; file length + POP HL ; boot address + LD A,E ; length MOD 256 + OR A + JR Z,JE7B1 ; only whole blocks + LD B,E ; the piece first +JE7AF: OTIR +JE7B1: LD B,0 ; and now only whole blocks + DEC D + JP P,JE7AF ; send another block + JP QPRMPT + ; + ; Check if a RAM disk is present + ; + ; input: C = I / O address + ; output: CY = 1 ... ram disk no + ; 0 ... ram disk is + ; nici: AF, if the ram disk is not, so is C + ; +@???RD: + XOR A + IN A,(C) ; at the beginning of the house + INC C ; cteci port + IN A,(C) ; honor byte + EX AF,AF' + DEC C + IN A,(C) ; again at the beginning + LD B,0A5H + INC C + INC C ; write port + OUT (C),B ; business A5 + DEC C + DEC C + IN A,(C) ; at the beginning + INC C + IN A,(C) ; honor, it should + CP B ; apartment A5 + JR NZ,JE7DF ; but it's not + DEC C ; control port + IN A,(C) ; again at the beginning + EX AF,AF' ; what was read + INC C ; will have to go back + INC C + OUT (C),A + DEC C + DEC C ; and the original C + RET ; mame RD =M CY = 0 +JE7DF: XOR A ; RD not connected + SCF ; CY = 1 + RET + ; +SRCPRG: DB 'R',0A1H,0B3H,9FH,0A1H,9DH,9CH,' ' + DB 9EH,9DH,0B7H,97H,'.',CR + ; Ramcard prog. +SMASTS: DB 4DH,0A1H,0A4H,96H,92H,9DH,' ',96H + DB 0A1H,9EH,92H,' ',0A4H,92H,96H,CR ; Master tape set + + + ;---------------------------------------------------- + ; + ; Cold start monitor + ; + ;---------------------------------------------------- + ORG 0E800H +COLD: + NOP + JP JE813 ; skip JUMP vector + JP QPRMPT ; monitor prompt +@COPYL: JP COPYL ; load file from CMT: +@COPYS: JP COPYS ; save file to CMT: +@COPYV: JP COPYV ; verify file on CMT: + JP @QDISK ; some EXEC (?, ... + ; +JE813: + DI + IM 1 + LD A,8 + OUT (PDMD),A ; MZ-700 mode settings + LD A,1 ; CRT settings: + OUT (PRF),A ; single color + OUT (PWF),A ; MZ-700 = DATA, ATB, CG + OUT (PMMC4 ),A ; mapped ROM, CGROM, VRAM + LD SP,NEWSP + CALL @INI55 + XOR A + LD DE,0 + CALL TIMST ; we start at midnight + LD BC,37 + CALL @944BC ; delay approx. 16.28 ms + LD BC,4*256+PCPR ; control PIO port + LD HL,TPIO ; bit mode, 6th and 7th bit as + OTIR ; output, other input, DI + LD BC,4*256+PCPR+1 ; PIO data port + OTIR ; bit mode, all output, DI + LD A,1 + OUT (0F7H),A + XOR A + OUT (0F7H),A ; turn off QD: + CALL BRKEY ; test CTRL + JR NC,JE862 ; CTRL not pressed + CP 20H + JP NZ,JE862 ; just SHIFT, we don't care + IN A,(PDMD) ; state of switch MZ-700 + AND 2 ; is ON? + JR Z,JE85F ; is, we leave the MZ-700 + XOR A + OUT (PDMD),A ; no, so MZ-800 + CALL @BLACK ; black display +JE85F: JP GORAM ; jump to RAM at 0 +JE862: LD B,4 ; turn off PSG + LD A,9FH +JE866: OUT (PPSG),A + ADD A,20H + DJNZ JE866 ; all registers are turned off + LD A,1 + LD (MCWR55),A ; ban on whistling from 8253 + LD A,5 + LD (MCWR55),A ; permission interrupted + LD B,0FFH ; zero + LD HL,FNAME ; buffer + CALL @F0B ; CMT control block + LD A,16H + CALL @PRNTC + LD A,71H ; filling VRAM + LD HL,ADRATB ; attribute 71H + CALL @FILLA + LD HL,38DH ; initialization + LD A,0C3H ; jump RST38 + LD (INTSRQ),A ; in RAM on + LD (INTADR),HL ; patricna mista + LD A,4 + LD (TEMPO),A ; medium speed tune + CALL MSTP ; stop MZ 700 music + CALL @IFNL? + CALL BEEP ; beep + LD A,1 ; beep on each key + LD (BPFLG),A ; will not + IN A,(PMMC0 ) ; mapping CGROM, CGRAM + LD DE,0C000H ; copied + LD HL,1000H ; character + LD BC,1000H ; degenerator + LDIR ; to VRAM + IN A,(PMMC1) ; unmaps CG + CALL @GETKY ; key pressed during RESET? + CP 'M' + JR Z,QMONIT ; to the monitor now + CP 'Q' + JR Z,JE91B ; clean from QD: + CP 'C' + JR Z,IPLCMT ; clean from CMT: + CALL @???FD ; we have floppy disks + JR NZ,IPLRD ; we don't +IPLFD: CALL @CLRS ; delete CRT: + CALL @FDBOOT ; cti program IPLPRO + JP QIPL ; return voice printing and RET + ; + ; Find out if we have FD: + ; + ; output: Z = 1 ... floppy disk found + ; Z = 0 ... we don't have a floppy disk + ; + ; nici: AF, B + ; +@???FD: + LD A,0A5H ; some constant + LD B,A + OUT (PFDTRK),A ; to the trace register + CALL @D125 ; wait for a while + IN A,(PFDTRK) ; and we read it back + CP B ; did she stay there? + RET ; if so, we have FD + ; + ; The entire MZ 800 screen will be black + ; + ; output: BC = 6CFH, A = 0 + ; +@BLACK: + PUSH HL + LD BC,5*256+PPAL ; pallet settings + LD HL,TBLACK ; all black + OTIR + XOR A + LD BC,6*256+PCRTC ; border register + OUT (C),A ; border take black + POP HL + RET + ; + ; Load the program from the RD disk, if it exists + ; +IPLRD: + LD C,0F8H + CALL @???RD ; do we have RD? + JP C,IPLQD ; we don't + CALL @RDLOAD ; The house is here, try to clean + LD DE,ERMG12 ; SRAM: check sum error + JP NZ,QIPL ; we don't have a ram disk + JP QGORD ; program from the RD and run + ; + CALL CLR3L ; delete the CRT and three times the CRLF + ; + ; + ; Display the initialization screen and wait for it to press + ; keys of any of the listed displays + ; +IPLKEY: CALL @MSGIN ; initialize screen + CALL @WNKEY ; until the key is pressed +JE90F: CALL @???QD + JR NZ,JE91E ; QD not connected + LD A,2 + CALL QKBD?? + CP 7FH ; pressed Q? +JE91B: JP Z,IPLQD ; Yes +JE91E: LD A,4 + CALL QKBD?? + CP 0DFH ; C pressed? + JR Z,IPLCMT ; Yes + LD C,A + CALL @???FD + JR NZ,JE932 ; FDs are not + LD A,C + CP 0FBH ; pressed F? + JR Z,IPLFD ; Yes +JE932: LD A,3 + CALL QKBD?? + CP 0F7H ; pressed M? + JR NZ,JE90F ; No + ; + ; List the header of the monitor and jump to its reading display + ; +QMONIT: + CALL @CLRS + LD DE,MONMSG + RST 18H + JP QPRMPT + ; + ; Program implementation from CMT + ; +IPLCMT: + LD HL,MPORTC ; is CMT? + LD A,(HL) + AND 10H + JR NZ,JE972 ; yes, you can start cleaning immediately + INC HL + LD A,6 + LD (HL),A ; up + INC A + LD (HL),A ; down + DEC HL + LD A,(HL) + AND 10H ; now he should go + JR NZ,JE972 ; yes, now he eats + CALL @CLRS + CALL @LETNL + CALL @LETNL + LD DE,IPLM1 ; Make ready CMT + CALL MSG12 +JE968: + CALL @BRKEY + JR Z,CMTER2 ; break + LD A,(HL) + AND 10H + JR Z,JE968 ; we are waiting for them to turn it on +JE972: + CALL @CLRS + CALL @LETNL + LD DE,IPLM4 ; IPL is looking ... + RST 18H + CALL @RHEAD + JP C,CMTER1 + CALL @CLRS + LD DE,IPLM0 ; IPL is loading .. + RST 18H + LD DE,FNAME ; file name + RST 18H + LD HL,(BEGIN) + EXX + LD HL,MGBASE ; boot address + LD (BEGIN),HL ; for now in the header + CALL @RDATA ; clean data from 1200 + JP C,CMTER1 ; error + ; + ; run the program loaded from CMT + ; +QGOCMT: + LD BC,100H ; tape recorder + EXX ; to BC ' + LD (BEGIN),HL ; actual boot address + LD HL,FSIZE ; to the header points to the length + JP QGOPGM ; start + ; + ; error returns + ; +CMTER1: + CP 2 +CMTER2: + LD DE,IPLM1 ; Make ready CMT + JR Z,JE9B4 + LD DE,ERRM2 ; CMT loading err. +JE9B4: + JP QIPL + ; + ; Load a program from QD + ; +IPLQD: + CALL @???QD ; mame QD? + LD A,2 + JR NZ,CMTER1 ; we don't, read from CMT + CALL JEEEC + CALL JEF27 + LD DE,IPLM2 ; Make ready QD + JR C,QIPL + CALL @CLRS + LD A,0DH + LD (IOBUF),A + CALL JF25F + LD A,1 + LD (M113A),A + LD HL,0EA04H + LD SP,NEWSP-2 + EX (SP),HL + CALL JEEF7 + JP C,JF202 + LD A,(HEAD) + CP 1 + LD DE,ERRM4 ; QD: File mode error + JR NZ,QDERR ; the mistake is really + LD DE,IPLM0 ; IPL is loading + RST 18H + JP JEEC2 + ; + LD DE,IPLM2 + ; + ; Error working with QD + ; +QDERR: + PUSH DE + LD A,6 + LD (M1130),A + CALL @QDISK + POP DE + JR QIPL + ; + ; List on the initialization message display without + ; 1. radku. According to the available equipment + ; writes a menu for selecting a display + ; Nothing all registers + ; +@MSGIN: + CALL @LETNL + LD DE,SELM0 ; Please push key + CALL MSG12 + CALL @LETNL + CALL @???FD + JR NZ,JEA1D ; not floppy + LD DE,SELM1 ; F: floppy disk + CALL MSG12 +JEA1D: CALL @???QD + JR NZ,JEA28 ; not QD + LD DE,SELM2 ; Q: quick disk + CALL MSG12 +JEA28: LD DE,SELM3 ; C: tape cassette + CALL MSG12 + LD DE,SELM4 ; M: monitor + JP MSG12 ; list and RET + ; + ; List of messages from DE on the display, list of help menus + ; MGIN and waiting for the keyboard to press + ; +QIPL: + CALL @CLRS + CALL @LETNL + CALL @LETNL + CALL MSG12 + JP IPLKEY + ; + ; Clear the display and CRLF 3 times on it + ; +CLR3L: + CALL @CLRS + LD B,3 +JEA48: CALL @LETNL + DJNZ JEA48 + RET + ; + ; Printing twelve spaces and messages on the display, which + ; the address is in the DE register + ; +MSG12: + LD B,12 ; number of spaces +JEA50: CALL @PRNTS ; gap + DJNZ JEA50 + RST 18H ; message from the DE register + JP @LETNL + ; + ; Clear the screen + ; + ; nici: AF + ; +@CLRS: + LD A,0C6H + JP @?DPCT + + ;---------------------------------------------------- + ; + ; MONITOR 9Z-504M + ; + ;---------------------------------------------------- +QPRMPT: + LD SP,NEWSP ; SP is in the area through which + CALL @IFNL? ; is mapping CG-ROMT + LD A,'*' + CALL @PRNTC + LD DE,IOBUF ; input buffer address + CALL @GETL +QPRMLOP: + LD A,(DE) + INC DE + CP CR + JR Z,QPRMPT + CP 'J' + JR Z,QJUMP ; jump to the program + CP 'L' + JP Z,QLOAD ; honor the program from CMT + CP 'F' + JR Z,QFLOPY ; honor the program from FD + CP 'B' + JP Z,QBEEP ; controlled keyboards + CP 'M' + JP Z,QMODIF ; memory modification + CP 'S' + JP Z,QSAVE ; save the program to a tape + CP 'V' + JP Z,QVERIF ; program verification + CP 'D' + JP Z,QDUMP ; HEXA memory dump + CP 'Q' + JR Z,QQDISK ; work with quick disk + CP 'E' + JR Z,QRCARD ; work with ram disk + CP 'G' + JR Z,QGOSUB ; jump to subroutine + JR QPRMLOP + ;---------------------------------------------------- + ; + ; J = jump + ; + ;---------------------------------------------------- +QJUMP: + CALL QHEXHL ; decode the address +QJPHL: JP (HL) ; and jump on her + ; + ; Called subroutines + ; + ;---------------------------------------------------- + ; + ; G = gosub (subroutine call) + ; + ;---------------------------------------------------- +QGOSUB: + CALL QHEXHL ; decode the address + CALL QJPHL ; call JP (HL) + JR QPRMPT + ;---------------------------------------------------- + ; + ; Q = quick disk (works with QD :) + ; + ;---------------------------------------------------- +QQDISK: + CALL @???QD ; mame QD: + JR NZ,QPRMPT ; no, that's why we won't be with him + CALL JEEEC ; work + LD HL,0 + LD (M113A),HL + LD A,(DE) ; kinds of display character + CP 'L' + JP Z,QQL ; read the program + CP 'S' + JP Z,QQS ; save the program + CP 'C' + JP Z,QQC ; program copy + CP 'F' + JP Z,QQF ; disk formatting + CP 'X' + JP Z,QQX ; program copy + CP 'D' + JP Z,QQD ; directory listing +QPRMP1: + JP QPRMPT + ;---------------------------------------------------- + ; + ; E = read and save program to RAM disk = + ; + ;---------------------------------------------------- + ; + ; E .... Work with RD + ; + ; ES ... Save the program from the cassette to the RD + ; EB ... Run program from RD + ; +QRCARD: + LD C,0F8H ; this is perhaps an I / O address + CALL @???RD ; RAM disk + JR NC,JEAF3 ; No, let's try + LD C,0A8H ; such an I / O address + CALL @???RD + JR C,QPRMP1 ; again, we probably don't have it +JEAF3: + LD A,(DE) ; 2nd character of the display + CP 'B' + JP Z,QEB ; run the program from the RD + CP 'S' + JP Z,QES ; program from CMT to RD + JR QPRMP1 + ;---------------------------------------------------- + ; + ; F = floppy (load program from floppy) + ; + ;---------------------------------------------------- +QFLOPY: + LD A,(DE) + CP CR + JR NZ,QPRMP1 ; must not be parameters + CALL @???FD ; do we have FD? + JR NZ,QPRMP1 ; No + CALL @FDBOOT ; read the file + CALL @IFNL? + RST 18H + JR QPRMP1 + ; + ; Find out if QD is connected + ; + ; output: Z = 1 ... QD connected + ; 0 ... QD does not exist + ; + ; nici: AF + ; +@???QD: + LD A,2 + OUT (0F7H),A + LD A,0A5H ; sample + OUT (0F7H),A ; write a sample + LD A,2 + OUT (0F7H),A + IN A,(0F7H) ; clean with QD + CP 0A5H ; compare with the sent sample + RET ; if there is a QD, it has to be equal + ; + ; statement CHECK SUM ERR. or BREAKT according to the error number, + ; return to monitor + ; +CMTERR: + LD DE,MGBRK ; BREAKT + CP 2 + JR Z,JEB2E ; it really was a break + LD DE,SCHECK ; check sum error +JEB2E: CALL @IFNL? + RST 18H + JR QPRMP1 ; to the monitor + ; +QGETL: + EX (SP),HL ; return address in HL + POP BC ; BC: = HL + LD DE,IOBUF + CALL @GETL + LD A,(DE) + CP 1BH + JR Z,QPRMP1 ; break + JP (HL) ; return + ; + ; Decodes 4 HEXA bytes from the input chain, + ; returns in HL. If the number cannot be decoded, + ; monitor control sales. + ; Nici: AF, IY + ; +QHEXHL: + EX (SP),IY ; return address + POP AF + CALL @HLHEX ; decode + JR C,QPRMP1 ; error + JP (IY) + ;---------------------------------------------------- + ; + ; L = load (load RAM on CMT) + ; + ;---------------------------------------------------- +QLOAD: + CALL @RFILE ; cti program + JR C,CMTERR ; failed + JP QGOCMT ; launch him + ; + ; Read CMT file from MGBASE (1200H) + ; + ; output: HL '= actual boot address + ; HL = address where the program was loaded (1200H) + ; + ; nici: DE + ; +@RFILE: + CALL RHEAD ; header + RET C ; not possible + CALL @IFNL? + LD DE,MSGLD ; Loading + RST 18H + LD DE,FNAME + RST 18H ; listing file name + LD HL,(BEGIN) ; actual boot address + EXX ; keep + LD HL,MGBASE ; always from 1200H + LD (BEGIN),HL + JP RDATA ; with honored data + ; + ; Copier - Load + ; +COPYL: + CALL @RFILE ; honor file + JR C,CMTERR ; error + EXX ; the correct address must + LD (BEGIN),HL ; data in the header for + JR @OKT ; COPYS and COPYV + ;---------------------------------------------------- + ; + ; M = modify + ; + ;---------------------------------------------------- +QMODIF: + CALL QHEXHL ; starting address +JEB7E: CALL @?NLHL ; write on new line + CALL @MHEX ; and byte to her + CALL PRNTS + CALL QGETL + CALL @HLHEX + JR C,JEBAA + CALL @IC4DE + INC DE + CALL @2HEX + JR C,JEB7E + CP (HL) + JR NZ,JEB7E + INC DE + LD A,(DE) + CP 0DH + JR Z,JEBA7 + CALL @2HEX + JR C,JEB7E + LD (HL),A +JEBA7: INC HL + JR JEB7E +JEBAA: LD H,B + LD L,C + JR JEB7E + ;---------------------------------------------------- + ; + ; S = save (save program to tape) + ; + ;---------------------------------------------------- +QSAVE: + CALL QFNAME ; honor name + LD HL,IOBUF + LD DE,FNAME + LD BC,11H + LDIR ; move to header + CALL QTOPA ; boot address + LD (BEGIN),HL + CALL QENDA ; end address + LD BC,(BEGIN) + SCF + SBC HL,BC ; calculate the length + INC HL + INC HL ; THIS INSTRUCTION IS IN ADDITION + LD (FSIZE),HL + CALL QEXCA ; start address + LD (ENTRY),HL + LD A,1 ; type always 1 = ORDER NO + LD (HEAD),A + CALL WHEAD ; write the header +JEBDF: JP C,CMTERR + CALL QWDATA ; write down the data +JEBE5: JP QPRMPT + ; + ; Kopirka - Save + ; +COPYS: + CALL WHEAD ; write header + JR C,JEBDF + LD HL,MGBASE ; the program is from 1200 + LD (BEGIN),HL ; impose + ; + ; Write data to the tape, in case of error make a report + ; sell monitor control + ; +QWDATA: + CALL WDATA ; write down the data + JR C,JEBDF ; error bounce + ; + ; List OKT on display + ; + ; nici: DE + ; +@OKT: + CALL @IFNL? + LD DE,942H + RST 18H + RET + ;---------------------------------------------------- + ; + ; V = verify (check the program on the tape + ; + ;---------------------------------------------------- +QVERIF: + CALL VERIF ; verify normally +JEC03: JP C,CMTERR + JP QOKT + ; + ; Copier - Verify + ; +COPYV: + CALL @VER12 ; This is to verify, however + JR C,JEC03 ; boot address 1200H + JR @OKT + ; + ; Verify with boot address 1200H + ; +@VER12: + DI + PUSH DE + PUSH BC + PUSH HL + LD BC,(FSIZE) ; length + LD HL,MGBASE ; replacement address + JP VERIF1 ; to the lower monitor + ;---------------------------------------------------- + ; + ; B = beep (controlled whistling after each key) + ; + ;---------------------------------------------------- +QBEEP: + LD A,(BPFLG) + RRA + CCF + RLA ; kind of condition than it was + LD (BPFLG),A +JEC27: JR JEBE5 + ;---------------------------------------------------- + ; + ; D = dump + ; + ;---------------------------------------------------- +QDUMP: + CALL QHEXHL + CALL @IC4DE + PUSH HL + CALL @HLHEX + POP DE + JR C,JEC87 +JEC36: EX DE,HL +JEC37: LD B,8 + LD C,17H + CALL @?NLHL +JEC3E: CALL @MHEX + INC HL + PUSH AF + LD A,(CURSOR) + ADD A,C + LD (CURSOR),A + POP AF + CP 20H + JR NC,JEC51 + LD A,2EH +JEC51: CALL @?ADCN + CALL PRNTA + LD A,(CURSOR) + INC C + SUB C + LD (CURSOR),A + DEC C + DEC C + DEC C + PUSH HL + SBC HL,DE + POP HL + JR Z,JEC84 + LD A,0F8H + LD (MKBOUT),A + NOP + LD A,(MKBDIN) + CP 0FEH + JR NZ,JEC78 + CALL @?BLNK +JEC78: DJNZ JEC3E +JEC7A: CALL @GETKD + OR A + JR Z,JEC7A + CALL BRKEY + JR NZ,JEC37 +JEC84: EQU 0EC84H + JR JEC27 +JEC87: LD HL,0A0H + ADD HL,DE + JR JEC36 + ; + ; Read the name of the file on the keyboard + ; +QFNAME: + CALL @IFNL? + LD DE,MSGV0 ; Filename? + RST 18H + LD DE,IOBUF + CALL @GETL + LD A,(DE) + CP 1BH ; break? + JR NZ,JECA4 ; No, all right +JEC9F: LD HL,QPRMPT + EX (SP),HL ; return to monitor + RET + ; +JECA4: LD B,0 ; name read + LD DE,IOBUF+10 ; this is where the name starts with + LD HL,IOBUF + LD A,(DE) ; name sign + CP CR + JR Z,JECD1 ; end of string +JECB1: ; ignore spaces before name + CP SPACE + JR NZ,JECB9 ; no gap + INC DE ; ignore space + LD A,(DE) + JR JECB1 ; another sign +JECB9: CP '"' + JR Z,JECC5 ; quotation marks as the 1st character +JECBD: LD (HL),A ; save the character at the beginning of the buffer + INC HL + INC B ; increase the length + LD A,17 + CP B ; bigger length than it should be? + JR Z,QFNAME ; yes, honor again +JECC5: INC DE + LD A,(DE) ; another sign + CP '"' + JR Z,JECCF ; quotes or CRs close + CP CR ; name + JR NZ,JECBD ; save the character and continue +JECCF: LD A,CR ; you have to save CR +JECD1: LD (HL),A + RET + ; + ; Honor the loading address + ; +QTOPA: + LD DE,MSGTA ; Top? + JR QHEXIN + ; + ; Honor the end address + ; +QENDA: + LD DE,MSGEA ; End? + JR QHEXIN + ; + ; Honor the start address + ; +QEXCA: + LD DE,MSGXA ; Exc? + ; + ; Print the string DE on the display and honor the HEXA number as follows + ; as long as it fails + ; +QHEXIN: + CALL @IFNL? + RST 18H ; list the appropriate voice + PUSH DE + LD DE,IOBUF + CALL @GETL ; honor string + LD A,(DE) + CP 1BH + POP DE + JR Z,JEC9F ; it was a break + PUSH DE ; permanent address introductory voice + LD DE,IOBUF+10 ; the number starts here + CALL @HLHEX ; try to decode + POP DE + JR C,QHEXIN ; wrong input + RET + ; + ; Sales of program loaded from 1200H, first + ; place where it belongs + ; + ; input: HL = address of the file size in the header + ; BC '= parameter sold by the program + ; +QGOPGM: + IN A,(PDMD) + BIT 1,A + JR Z,JED08 ; MZ 700 mod + XOR A + OUT (PDMD),A ; MZ 800 mod + CALL @BLACK ; black screen +JED08: LD C,(HL) ; BC: = length + INC HL + LD B,(HL) + INC HL + LD E,(HL) ; DE: = address + LD A,(HL) + INC HL + LD D,(HL) + OR (HL) + PUSH DE ; hide address + INC HL + LD E,(HL) ; DE: = start address + OR (HL) + INC HL + LD D,(HL) + OR (HL) + PUSH DE + POP IX ; IX = start address + POP DE ; boot address + JR NZ,JED20 ; if the bootloader and boot address are + OUT (PMMC0 ),A ; zero, map down to RAM +JED20: LD HL,MGBASE + LD A,MGBASE/256 ; address of the program page + CP D + JR C,JED2E ; the program will be over 1200 + JR NZ,JED3E ; the program will be below 1200 + XOR A ; will be from 1200 to 12FF + CP E ; CURRENT, ADMINISTRATELY APARTMENT + JR NC,JED3E ; JR NC, JED40 +JED2E: DEC BC ; the program will be over 1200 + PUSH HL ; addresses must be edited + LD HL,0 ; reading length + ADD HL,DE ; and reading the unit + ADD HL,BC + PUSH HL + POP DE + POP HL + ADD HL,BC + INC BC + LDDR + JR JED40 ; run +JED3E: ; program below 1200, it's easy + LDIR +JED40: + EXX ; to the BC start parameter + JP (IX) + + + ; Please push key +SELM0: DB 050H, 0b8H, 092H, 0a1H, 0a4H, 092H, 020H, 09eH, 0a5H, 0a4H, 098H, 020H, 0a9H, 092H, 0bdH, CR + ; F: Floppy disk +SELM1: DB 046H, 03aH, 046H, 0b8H, 0b7H, 09eH, 09eH, 0bdH, 020H, 09cH, 0a6H, 0a4H, 0a9H, CR + ; Q: Quick disk +SELM2: DB 051H, 03aH, 051H, 0a5H, 0a6H, 09fH, 0a9H, 020H, 09cH, 0a6H, 0a4H, 0a9H, CR + ; C: Cassette tape +SELM3: DB 043H, 03aH, 043H, 0a1H, 0a4H, 0a4H, 092H, 096H, 096H, 092H, 020H, 096H, 0a1H, 09eH, 092H, CR + ; M: Monitor +SELM4: DB 04dH, 03aH, 04dH, 0b7H, 0b0H, 0a6H, 096H, 0b7H, 09dH, CR + ; IPL is loading +IPLM0: DB 049H, 050H, 04cH, 020H, 0a6H, 0a4H, 020H, 0b8H, 0b7H, 0a1H, 09cH, 0a6H, 0b0H, 097H, 020H, CR + ; Make ready CMT +IPLM1: DB 04dH, 0a1H, 0a9H, 092H, 020H, 09dH, 092H, 0a1H, 09cH, 0bdH, 020H, 043H, 04dH, 054H, CR + ; Make ready QD +IPLM2: DB 04dH, 0a1H, 0a9H, 092H, 020H, 09dH, 092H, 0a1H, 09cH, 0bdH, 020H, 051H, 044H, CR + ; Make ready FD +IPLM3: DB 04dH, 0a1H, 0a9H, 092H, 020H, 09dH, 092H, 0a1H, 09cH, 0bdH, 020H, 046H, 044H, CR + ; IPL is looking for a program +IPLM4: DB 020H, 020H, 020H, 020H, 020H, 049H, 050H, 04cH, 020H, 0a6H, 0a4H, 020H, 0b8H, 0b7H, 0b7H, 0a9H, 0a6H, 0b0H, 097H, 020H, 0aaH, 0b7H, 09dH, 020H, 0a1H, 020H, 09eH, 09dH, 0b7H, 097H, 09dH, 0a1H, 0b3H, CR + ; FD: Loading err +ERRM0: DB 046H, 044H, 03aH, 04cH, 0b7H, 0a1H, 09cH, 0a6H, 0b0H, 097H, 020H, 092H, 09dH, 09dH, 0b7H, 09dH, CR + ; FD: Not master +ERRM1: DB 046H, 044H, 03aH, 04eH, 0b7H, 096H, 020H, 0b3H, 0a1H, 0a4H, 096H, 092H, 09dH, CR + ; CMT: Loading error +ERRM2: DB 043H, 04dH, 054H, 03aH, 04cH, 0b7H, 0a1H, 09cH, 0a6H, 0b0H, 097H, 020H, 092H, 09dH, 09dH, 0b7H, 09dH, CR + ; QD: Loading error +ERRM3: DB 051H, 044H, 03aH, 04cH, 0b7H, 0a1H, 09cH, 0a6H, 0b0H, 097H, 020H, 092H, 09dH, 09dH, 0b7H, 09dH, CR + ; QD: File mode error +ERRM4: DB 051H, 044H, 03aH, 046H, 0a6H, 0b8H, 092H, 020H, 0b3H, 0b7H, 09cH, 092H, 020H, 092H, 09dH, 09dH, 0b7H, 09dH, CR + ; SRAM: Checksum error +ERMG12: DB 053H, 052H, 041H, 04dH, 03aH, 043H, 098H, 092H, 09fH, 0a9H, 020H, 0a4H, 0a5H, 0b3H, 020H, 092H, 09dH, 09dH, CR + ; ** MONITOR 9Z-504M ** +MONMSG: DB "** MONITOR 9Z-504MA **", CR + ; Filename? +MSGV0: DB 046H, 0a6H, 0b8H, 092H, 0b0H, 0a1H, 0b3H, 092H, 03fH, 020H, CR + ; Top address? +MSGTA: DB 054H, 0b7H, 09eH, 020H, 0a1H, 09cH, 09dH, 0a4H, 03fH, 020H, CR + ; Exc address? +MSGEA: DB 045H, 0b0H, 09cH, 020H, 0a1H, 09cH, 09dH, 0a4H, 03fH, 020H, CR + ; End address? +MSGXA: DB 045H, 09bH, 09fH, 020H, 0a1H, 09cH, 09dH, 0a4H, 03fH, 020H, CR + ; Loading +MSGLD: DB 04cH, 0b7H, 0a1H, 09cH, 0a6H, 0b0H, 097H, 020H, CR + + ; + ; + ; Initialization tables for PIO + ; +TPIO: DB 0,0CFH,3FH,7 + DB 0,0CFH,0,7 + ; + ; Initialization table for PAL + ; +TBLACK: DB 0,10H,20H,30H,40H + + ;---------------------------------------------------- + ; + ; Monitoring displays for QD + ; + ;---------------------------------------------------- +QQL: + CALL JEF27 + JR C,JEEE0 + CALL QFNAME + CALL JF25F + LD DE,MSGLD + RST 18H +JEEB6: + CALL JEEF7 + JR C,JEEE0 + LD A,(HEAD) + CP 1 + JR NZ,JEEB6 +JEEC2: + LD DE,FNAME + RST 18H + LD HL,MGBASE + JR JEECE + ; + LD HL,(ENTRY) +JEECE: + LD (M1132),HL + LD HL,(BEGIN) + LD (M1134),HL + LD HL,103H + LD (M1130),HL + CALL @QDISK +JEEE0: + JR C,JEF31 + LD BC,300H + EXX + LD HL,BEGIN + JP QGOPGM + ; +JEEEC: + XOR A + LD (M1144),A + LD (M113F),A + LD (M1141),A + RET + ; +JEEF7: + LD HL,3 + LD (M1130),HL + LD HL,HEAD + LD (M1132),HL + LD HL,40H + LD (M1134),HL +JEF09: + CALL @QDISK + RET C + LD A,(IOBUF) + CP 0DH + RET Z + LD HL,IOBUF + LD DE,FNAME + LD B,11H +JEF1B: + LD A,(DE) + CP (HL) + JR NZ,JEF09 + CP 0DH + RET Z + INC DE + INC HL + DJNZ JEF1B + RET + ; +JEF27: + XOR A + LD (M1131),A + JP JEFE6 + ; +QQS: + CALL JEFE1 +JEF31: + JR C,JEF92 + CALL QFNAME + LD A,(IOBUF) + CP 0DH + JR Z,QQS + LD HL,IOBUF + LD DE,FNAME + LD BC,11H + LDIR + CALL QTOPA + LD (ENTRY),HL + CALL QENDA + OR A + LD BC,(ENTRY) + SBC HL,BC + INC HL + LD (BEGIN),HL + CALL QEXCA + LD (RDCRC),HL + LD A,1 + LD (HEAD),A + CALL JEF9F + JR C,JEF92 + CP 28H + JP NZ,JF202 + LD HL,(ENTRY) +JEF74: + LD (M1136),HL + LD HL,404H + LD (M1130),HL + LD HL,HEAD + LD (M1132),HL + LD HL,40H + LD (M1134),HL + LD HL,(BEGIN) + LD (M1138),HL + CALL @QDISK +JEF92: + JP C,JF028 +QOKT: + CALL @IFNL? + LD DE,TTYP + RST 18H + JP QPRMPT + ; +JEF9F: + CALL JF25F + LD HL,3 + LD (M1130),HL + LD HL,IOBUF + LD (M1132),HL + LD HL,40H + LD (M1134),HL + XOR A + LD (M113C),A +JEFB8: + LD A,(M113C) + INC A + CP 21H + LD (M113C),A + LD A,33H + RET NC + CALL @QDISK + CCF + RET NC + LD DE,11A4H + LD HL,FNAME + LD B,11H +JEFD1: + LD A,(DE) + CP (HL) + JR NZ,JEFB8 + CP 0DH + JR Z,JEFDD + INC DE + INC HL + DJNZ JEFD1 +JEFDD: + LD A,2AH + SCF + RET + ; +JEFE1: + LD A,0FFH + LD (M1131),A +JEFE6: + LD A,1 + LD (M1130),A + CALL @QDISK + RET + ; +QQD: + CALL JEF27 + JR C,JF028 + CALL JF25F + LD B,0 + CALL @IFNL? + LD DE,DIRMSG + RST 18H + LD HL,DIRQD +JF003: + LD (M1132),HL + LD HL,3 + LD (M1130),HL + LD HL,40H + LD (M1134),HL + PUSH BC + CALL @QDISK + POP BC + JR C,JF023 + INC B + LD HL,(M1132) + LD DE,12H + ADD HL,DE + JR JF003 + ; +JF023: + CP 28H + JR Z,JF02B + SCF +JF028: + JP C,JF0C9 +JF02B: + LD A,6 + LD (M1130),A + PUSH BC + CALL @QDISK + POP BC + XOR A + CP B + JR NC,JF0B2 + CALL @IFNL? + LD HL,DIRQD +JF03F: + LD A,(HL) + LD DE,TTYP+1*4 + DEC A + JR Z,JF07C + LD DE,TTYP+2*4 + DEC A + JR Z,JF07C + LD DE,TTYP+3*4 + DEC A + JR Z,JF07C + LD DE,TTYP+4*4 + DEC A + JR Z,JF07C + LD DE,TTYP+5*4 + DEC A + JR Z,JF07C + DEC A + JR Z,JF079 + LD DE,TTYP+6*4 + DEC A + JR Z,JF07C + DEC A + JR Z,JF079 + DEC A + JR Z,JF079 + LD DE,TTYP+7*4 + DEC A + JR Z,JF07C + LD DE,TTYP+8*4 + DEC A + JR Z,JF07C +JF079: + LD DE,TTYP+9*4 +JF07C: + PUSH BC + LD B,4 +JF07F: + CALL @PRNTS + DJNZ JF07F + POP BC + RST 18H + CALL @PRNTS + CALL @PRNTS + CALL @PRNTS + LD A,22H + CALL @PRNTC + INC HL + PUSH HL + POP DE + RST 18H + LD A,22H + CALL @PRNTC + CALL @IFNL? + LD DE,11H + ADD HL,DE +JF0A4: + CALL @GETKD + OR A + JR Z,JF0A4 + CALL BRKEY + JP Z,QPRMPT + DJNZ JF03F +JF0B2: + JP QOKT + ; +QQF: + LD DE,0F330H + RST 18H + CALL JF0CE + CALL JEFE1 + JR C,JF0C9 + LD A,2 + LD (M1130),A + CALL @QDISK +JF0C9: + JP C,JF160 + JR JF0B2 + ; +JF0CE: + CALL @IFNL? + LD DE,QDCM0 + RST 18H + CALL @WNKEY + CALL @?PONT + LD A,0EFH +JF0DD: + LD (HL),A + CALL JF0EB + JR C,JF0E8 + LD A,(HL) + XOR 0EFH + JR JF0DD + ; +JF0E8: + XOR A + LD (HL),A + RET + ; +JF0EB: + LD BC,6 +JF0EE: + DEC BC + LD A,B + OR C + RET Z + LD A,1 + CALL QKBD?? + CP 7FH + SCF + RET Z + LD A,3 + CALL QKBD?? + CP 0FBH + JR Z,JF10D + LD A,8 + CALL QKBD?? + CP 7EH + JR NZ,JF0EE +JF10D: + XOR A + LD (HL),A + LD SP,NEWSP + JP QPRMPT + ; +QKBD??: + PUSH HL + LD HL,MKBOUT + LD (HL),A + INC HL +JF11B: LD A,(HL) + PUSH AF + PUSH BC + LD B,14H +JF120: + CALL @D1200 + DJNZ JF120 + POP BC + POP AF + CP (HL) + JR NZ,JF11B + POP HL + RET + ; +QQC: + CALL JEF27 + JR C,JF160 + CALL QFNAME + LD A,(IOBUF) + CP 0DH + JR Z,QQC + CALL JF25F + LD DE,MSGLD + RST 18H + CALL JEEF7 + JR C,JF160 + LD DE,FNAME + RST 18H + LD HL,MGBASE + LD (M1132),HL + LD HL,(BEGIN) + LD (M1134),HL + LD HL,103H + LD (M1130),HL + CALL @QDISK +JF160: + JR C,JF183 + CALL @BELL + CALL @IFNL? + LD DE,QDQCM + RST 18H + LD A,2 + LD (M113A),A + LD HL,0F16CH + LD SP,NEWSP-2 + EX (SP),HL + CALL JF0CE +JF17B: + CALL JEFE1 + JR C,JF183 + CALL JEF9F +JF183: + JP C,JF202 + CP 28H + JP NZ,JF202 + LD HL,MGBASE + JP JEF74 + ; +@WNKEY: + LD B,0AH +JF193: + LD HL,MKBOUT + DEC B + LD (HL),B + INC B + INC HL + LD A,(HL) + CP 0FFH + JR NZ,@WNKEY + DJNZ JF193 + RET + ; +QQX: + CALL @RFILE + JP C,CMTERR + EXX + LD (BEGIN),HL + CALL @BELL +JF1AF: + CALL QFNAME + LD A,(IOBUF) + CP 0DH + JR Z,JF1AF + LD HL,IOBUF + LD DE,FNAME + LD BC,11H + LDIR + CALL @IFNL? + LD DE,QDQCM + RST 18H + LD A,(HEAD) + CP 4 + JR Z,JF1D8 + CP 5 + JR NZ,JF1DC + DEC A + DEC A +JF1D8: + DEC A + LD (HEAD),A +JF1DC: + LD HL,112EH + LD DE,1130H + LD BC,2DH + LDDR + LD HL,0 + LD (FSIZE),HL + LD A,2 + LD (M113A),A + LD HL,0F1EDH + LD SP,NEWSP-2 + EX (SP),HL + CALL JF0CE + CALL JEEEC + JP JF17B + ; +JF202: + LD DE,0F290H + CP 28H + JR Z,JF244 + LD DE,MGBDE + CP 39H + JR Z,JF244 + LD DE,MGWPT + CP 2EH + JR Z,JF244 + LD DE,MGNRE + CP 32H + JR Z,JF244 + LD DE,MGNSE + CP 35H + JR Z,JF244 + LD DE,MGUFE + CP 36H + JR Z,JF244 + LD DE,MGALE + CP 2AH + JR Z,JF244 + LD DE,MGTME + CP 33H + JR Z,JF244 + LD DE,MGBRK + CP 0 + JR Z,JF244 + LD DE,MGHDE +JF244: + LD A,6 + LD (M1130),A + CALL @QDISK + CALL JF25F + LD A,(M113A) + RRA + RET C + PUSH AF + CALL @IFNL? + RST 18H + POP AF + RRA + RET C + JP QPRMPT + ; +JF25F: + LD A,5 + LD (M1130),A + CALL @QDISK + RET + ; + ; Program type table. + ; +TTYP: DB "OK!" + DB 0DH + DB "OBJ" + DB 0DH + DB "BTX" + DB 0DH + DB "BSD" + DB 0DH + DB "BRD" + DB 0DH + DB "RB " + DB 0DH + DB "LIB" + DB 0DH + DB "SYS" + DB 0DH + DB "GR " + DB 0DH + DB "???" + DB 0DH + + ; QD: File not found +MGNFE: DB 051H, 044H, 03aH, 046H, 0a6H, 0b8H, 092H, 020H, 0b0H, 0b7H, 096H, 020H, 0aaH, 0b7H, 0a5H, 0b0H, 09cH, CR + ; QD: Too many files +MGTME: DB 051H, 044H, 03aH, 054H, 0b7H, 0b7H, 020H, 0b3H, 0a1H, 0b0H, 0bdH, 020H, 0aaH, 0a6H, 0b8H, 092H, 0a4H, 020H, 092H, 09dH, 09dH, CR + ; QD: Hard err +MGHDE: DB 051H, 044H, 03aH, 048H, 0a1H, 09dH, 09cH, 020H, 092H, 09dH, 09dH, CR + ; Already exist err +MGALE: DB 041H, 0b8H, 09dH, 092H, 0a1H, 09cH, 0bdH, 020H, 092H, 09bH, 0a6H, 0a4H, 096H, 020H, 092H, 09dH, 09dH, CR + ; QD: Write protect +MGWPT: DB 051H, 044H, 03aH, 057H, 09dH, 0a6H, 096H, 092H, 020H, 09eH, 09dH, 0b7H, 096H, 092H, 09fH, 096H, CR + ; QD: Not ready +MGNRE: DB 051H, 044H, 03aH, 04eH, 0b7H, 096H, 020H, 09dH, 092H, 0a1H, 09cH, 0bdH, CR + ; QD: No file space +MGNSE: DB 051H, 044H, 03aH, 04eH, 0b7H, 020H, 0aaH, 0a6H, 0b8H, 092H, 020H, 0a4H, 09eH, 0a1H, 09fH, 092H, 020H, 092H, 09dH, 09dH, CR + ; QD: Unformat err +MGUFE: DB 051H, 044H, 03aH, 055H, 0b0H, 0aaH, 0b7H, 09dH, 0b3H, 0a1H, 096H, 020H, 092H, 09dH, 09dH, CR + ; QD: Bad disk err +MGBDE: DB 051H, 044H, 03aH, 042H, 0a1H, 09cH, 020H, 09cH, 0a6H, 0a4H, 0a9H, 020H, 092H, 09dH, 09dH, CR + ; BreakT +MGBRK: DB 042H, 09dH, 092H, 0a1H, 0a9H, 021H, CR + ; QD: Formatting +QDFMG: DB 051H, 044H, 03aH, 046H, 0b7H, 09dH, 0b3H, 0a1H, 096H, 096H, 0a6H, 0b0H, 097H, CR + ; Set destination disk +QDQCM: DB 053H, 092H, 096H, 020H, 09cH, 092H, 0a4H, 096H, 0a6H, 0b0H, 0a1H, 096H, 0a6H, 0b7H, 0b0H, 020H, 09cH, 0a6H, 0a4H, 0a9H, CR + ; OK? (Y / N) +QDCM0: DB 04fH, 04bH, 03fH, 028H, 059H, 02fH, 04eH, 029H, CR + ; Directory of QD: +DIRMSG: DB 044H, 0a6H, 09dH, 092H, 09fH, 096H, 0b7H, 09dH, 0bdH, 020H, 0b7H, 0aaH, 020H, 051H, 044H, 03aH, CR + + ; + ALIGN 0F380H + ; +JF380: + LD A,0C0H + OUT (0F6H),A + RET + + ALIGN 0F400H + ; + ; + ; EQU table, they are described in detail + ; in the lower monitor + ; +INTSRQ: EQU 01038H +INTADR: EQU 01039H +HEAD: EQU 010F0H +NEWSP: EQU HEAD +FNAME: EQU 010F1H +FSIZE: EQU 01102H +BEGIN: EQU 01104H +ENTRY: EQU 01106H +RDCRC: EQU 01108H +RDADR: EQU 0110AH +MGBASE: EQU 01200H +OLDSP: EQU 01148H +CONMOD: EQU 01170H +CURSOR: EQU 01171H +CURCH: EQU 01192H +CSRH: EQU 01194H +TMLONG: EQU 01195H +MGCRC: EQU 01197H +MGCRCV: EQU 01199H +AMPM: EQU 0119BH +EIFLG: EQU 0119CH +BPFLG: EQU 0119DH +TEMPO: EQU 0119EH +OKTNUM: EQU 011A0H +FREQ: EQU 011A1H +IOBUF: EQU 011A3H + ; + ; Variables for working with QD: + ; +M1130: EQU 01130H +M1131: EQU 01131H +M1132: EQU 01132H +M1134: EQU 01134H +M1136: EQU 01136H +M1138: EQU 01138H +M113A: EQU 0113AH +M113C: EQU 0113CH +M113D: EQU 0113DH +M113E: EQU 0113EH +M113F: EQU 0113FH +M1140: EQU 01140H +M1141: EQU 01141H +M1142: EQU 01142H +M1143: EQU 01143H +M1144: EQU 01144H +M1145: EQU 01145H + ; +DIRQD: EQU 0CD90H ; buffer for QD directory + ; + ; Variables used by FD subroutines + ; +FDCB: EQU 0CEE9H ; FD parameter block +FDCMD: EQU 0CEF4H ; last view of the controller +FDON?: EQU 0CEF5H ; mechanic on flag +TFDRES: EQU 0CEF6H ; table of mounted disks +FDSTAT: EQU 0CEFBH ; status read last +FDARET: EQU 0CEFEH ; return address in case of error +FDHEAD: EQU 0CF00H ; program header on FD + ; + ; BINDINGS HORNI ==M DOLNI + ; +SCHECK: EQU 0147H +@2HEX: EQU 041FH +@??KEY: EQU 09B3H +@?ADCN: EQU 0BB9H +@?BLNK: EQU 0DA6H +@?DACN: EQU 0BCEH +@?DPCT: EQU 0DDCH +@?PONT: EQU 0FB1H +@ASC: EQU 03DAH +@BELL: EQU 003EH +@BRKEY: EQU 001EH +@IFNL?: EQU 0009H +IFNL?: EQU 0918H +@GETKY: EQU 001BH +@GETL: EQU 0003H +@HEX: EQU 03F9H +@HLHEX: EQU 0410H +@LETNL: EQU 0006H +@MELDY: EQU 0030H +@MSG: EQU 0015H +@MSTA: EQU 0044H +@MSTP: EQU 0047H +@PRNTC: EQU 0012H +@PRNTS: EQU 000CH +@TIMRD: EQU 003BH +@TIMST: EQU 0033H +@XTEMP: EQU 0041H +@RHEAD: EQU 0027H +@RDATA: EQU 002AH +GORAM: EQU 005BH +@IC4DE: EQU 02A6H +MSTP: EQU 02BEH +TIMST: EQU 0308H +@MHEX: EQU 03B1H +WHEAD: EQU 0436H +WDATA: EQU 0475H +RHEAD: EQU 04D8H +RDATA: EQU 04F8H +BEEP: EQU 0577H +VERIF: EQU 0588H +VERIF1: EQU 0593H +@?NLHL: EQU 05FAH +@INI55: EQU 073EH +@GETKD: EQU 08CAH +PRNTS: EQU 0920H +PRNTA: EQU 096CH +@FILLA: EQU 09D5H +BRKEY: EQU 0A32H +@F0B: EQU 0FD8H ; END MARKER + END + + diff --git a/software/asm/MZ800_IOCS.asm b/software/asm/MZ800_IOCS.asm new file mode 100644 index 0000000..806d0ae --- /dev/null +++ b/software/asm/MZ800_IOCS.asm @@ -0,0 +1,1607 @@ + ; + ; + ; SHARPMZ - 821 + ; (ROM contents, upper monitor E000-F3FF) + ; + ; + ; Input / Output address + INCLUDE "Macros.asm" + +BRKEY: EQU 0001EH + + ORG 0F400H + + JP LF6C8 + JP LF8FF + JP LF96A + JP LF9DC + JP LFA3D + JP LF7D0 + JP LF5C1 + JP LF5AD + JP LF47A + JP LF62F + JP LF566 + JP LF543 + JP LF551 + JP LF53C + JP LF512 + JP LFA90 + JP LFA62 + JP LF905 + JP LF961 + ADD A,007H + SRL A + SRL A + SRL A + RET + + XOR A + LD B,003H +LF445: SLA C + RLA + DJNZ LF445 ; (-005H) + LD B,A + RET + +LF44C: PUSH BC + LD C,A + LD B,000H + ADD HL,BC + POP BC + RET + +LF453: LD A,(HL) + LD (DE),A + INC HL + INC DE + DJNZ LF453 ; (-006H) + RET + +LF45A: EX (SP),IX + PUSH HL + PUSH BC + PUSH DE + PUSH AF + PUSH HL + LD HL,LF473 + EX (SP),HL + JP (IX) +LF467: EX (SP),IX + PUSH HL + PUSH BC + PUSH DE + PUSH HL + LD HL,LF474 + EX (SP),HL + JP (IX) +LF473: POP AF +LF474: POP DE + POP BC + POP HL + POP IX + RET + +LF47A: LD HL,(012AEH) + RET C + + CALL LF737 + NOP + JP Z,LF566 + PUSH HL +LF486: POP HL +LF487: CALL LF737 + NOP + RET Z + + INC HL + CP 02CH + JR Z,LF487 ; (-00aH) + CP 04DH + JR Z,LF4E3 ; (+04eH) + CP 053H + JR Z,LF4CC ; (+033H) + CP 051H + JR Z,LF4B1 ; (+014H) + DEC HL + CP 024H + JR Z,LF4A8 ; (+006H) + SUB 030H + CP 00AH + JR NC,LF4FF ; (+057H) +LF4A8: CALL LF76F + LD A,E + LD (01093H),A + JR LF487 ; (-02aH) +LF4B1: LD B,008H + CALL LF4F5 + XOR A + LD A,E + AND 001H + LD (013CAH),A + LD A,E + RR A + RRC A + RRC A + LD (013CBH),A + CALL LF566 + JR LF487 ; (-045H) +LF4CC: LD A,(013D8H) + LD B,A + CALL LF4F5 + LD B,A + INC B + XOR A + SCF +LF4D7: ADC A,A + DJNZ LF4D7 ; (-003H) + LD (01092H),A + XOR A + LD (0108FH),A + JR LF487 ; (-05cH) +LF4E3: LD B,003H + CALL LF4F5 + PUSH HL + LD HL,LF486 + PUSH HL + OR A + JR Z,LF50F ; (+01fH) + DEC A + JR Z,LF525 ; (+032H) + JR LF51B ; (+026H) +LF4F5: CALL LF76F + LD A,D + OR A + JR NZ,LF4FF ; (+003H) + LD A,E + CP B + RET C + +LF4FF: LD A,003H +LF501: LD B,0FFH +LF503: LD HL,013D9H + LD (HL),B + LD SP,012A8H + RET + +LF50B: LD A,03BH + JR LF501 ; (-00eH) +LF50F: CALL LF566 +LF512: CALL LF70F +LF515: LD HL,013D6H + RES 7,(HL) + RET + +LF51B: LD A,(013D6H) + BIT 7,A + RET Z + + LD B,002H + JR LF503 ; (-022H) +LF525: LD HL,013D6H + BIT 7,(HL) + RET NZ + + CALL LF70F + LD A,(013C3H) + CP 003H + JR NZ,LF50B ; (-02aH) + LD A,083H + OUT (0FDH),A + SET 7,(HL) + RET + +LF53C: LD HL,013D6H + BIT 0,(HL) + JR Z,LF551 ; (+00eH) +LF543: PUSH HL + LD HL,013D6H + BIT 0,(HL) + JR Z,LF564 ; (+019H) + RES 0,(HL) + RES 1,(HL) + JR LF564 ; (+013H) +LF551: PUSH HL + LD HL,013D6H + BIT 7,(HL) + JR Z,LF564 ; (+00bH) + BIT 0,(HL) + JR NZ,LF564 ; (+007H) + SET 0,(HL) + BIT 1,(HL) + CALL NZ,LF6BE +LF564: POP HL + RET + +LF566: CALL LF467 + CALL LF543 + LD HL,00000H + LD (013CEH),HL + LD HL,00000H + CALL LF764 + EX DE,HL + LD (013D0H),HL + LD (013D2H),HL + LD (013D4H),HL + EX DE,HL + LD HL,VERSION + SBC HL,DE + LD (013CCH),HL + XOR A + LD (013D7H),A + LD A,(013C3H) + CP 003H + CALL NZ,LF515 + CALL LF705 + RET + +LF59B: LD A,(01093H) + CALL LF62F + BIT 4,C + LD A,01AH + CALL NZ,LF636 + XOR A + LD (01095H),A + RET + +LF5AD: CALL LF45A + LD B,A + LD A,(0108FH) + OR A + LD A,B + LD E,0FFH + JR Z,LF5CC ; (+012H) + RET + +LF5BB: LD IX,LF636 + JP (IY) +LF5C1: CALL LF45A + LD B,A + LD A,(0108FH) + OR A + LD E,000H + RET NZ + +LF5CC: LD A,(01097H) + DEC A + LD A,044H + JP NZ,LF657 + LD A,(01092H) + LD C,A + LD A,B + CP 00DH + JR Z,LF59B ; (-043H) + LD HL,01095H + INC (HL) + BIT 2,C + JR NZ,LF5BB ; (-02bH) + CP 020H + JR NC,LF636 ; (+04cH) + BIT 0,E + JR Z,LF5FE ; (+010H) + SUB 011H + CP 006H + JR C,LF637 ; (+043H) + SUB 0F4H + CP 002H + JR NC,LF634 ; (+03aH) + LD A,02EH + JR LF636 ; (+038H) +LF5FE: BIT 3,C + JR NZ,LF636 ; (+034H) + LD HL,01095H + DEC (HL) + LD A,B + CP 015H + LD B,00FH + JR Z,LF637 ; (+02aH) + CP 00CH + JR Z,LF637 ; (+026H) + CP 011H + LD B,009H + JR Z,LF637 ; (+020H) + CP 012H + LD B,00BH + JR Z,LF637 ; (+01aH) + CP 016H + JR NZ,LF636 ; (+015H) + LD A,00CH + CALL LF636 + LD A,00AH + CALL LF636 + LD A,003H + JR LF636 ; (+007H) +LF62F: CALL LF45A + JR LF636 ; (+002H) +LF634: LD A,020H +LF636: LD B,A +LF637: LD A,(01092H) + BIT 1,A + JR Z,LF662 ; (+024H) + LD HL,013D7H + LD A,(HL) + CP 002H + JR Z,LF650 ; (+00aH) + LD A,B + INC (HL) + CP 00BH + JR Z,LF662 ; (+016H) + LD (HL),000H + JR LF662 ; (+012H) +LF650: LD A,(013D6H) + BIT 7,A + JR Z,LF662 ; (+00bH) +LF657: LD A,0C4H + LD HL,(0106EH) + LD (01044H),HL + JP LF501 +LF662: LD A,(013D6H) + BIT 7,A + JR NZ,LF670 ; (+007H) + CALL LF70F + LD A,B + JP LF6F0 +LF670: CALL LF551 + LD A,(01094H) + LD C,A +LF677: LD HL,03390H +LF67A: CALL LF6B0 + JR NC,LF68A ; (+00bH) + DEC HL + LD A,H + OR L + JR NZ,LF67A ; (-00aH) + DEC C + JR NZ,LF677 ; (-010H) + JP LF731 +LF68A: LD HL,(013CEH) + LD A,H + OR L + INC HL + LD (013CEH),HL + JR NZ,LF69D ; (+008H) + CALL LF70F + LD A,B + CALL LF6F0 + RET + +LF69D: LD HL,(013D0H) + LD A,B + CALL LF743 + INC HL + LD A,H + OR L + JR NZ,LF6AC ; (+003H) + LD HL,(013D4H) +LF6AC: LD (013D0H),HL + RET + +LF6B0: CALL LF467 + LD HL,(013CCH) + LD DE,(013CEH) + OR A + SBC HL,DE + RET + +LF6BE: PUSH AF + PUSH HL + PUSH BC + CALL LF6C8 + POP BC + POP HL + POP AF + RET + +LF6C8: LD HL,013D6H + SET 1,(HL) + BIT 0,(HL) + RET Z + + LD HL,(013CEH) + LD A,H + OR L + RET Z + + DEC HL + LD A,H + OR L + LD (013CEH),HL + RET Z + + LD HL,(013D2H) + CALL LF74E + LD B,A + INC HL + LD A,H + OR L + JR NZ,LF6EC ; (+003H) + LD HL,(013D4H) +LF6EC: LD (013D2H),HL + LD A,B +LF6F0: OUT (0FFH),A + LD A,080H + CALL LF706 + LD A,(013CAH) + OR A + JR NZ,LF705 ; (+008H) +LF6FD: IN A,(0FEH) + AND 00DH + CP 001H + JR NZ,LF6FD ; (-008H) +LF705: XOR A +LF706: PUSH HL + LD HL,013CBH + XOR (HL) + POP HL + OUT (0FEH),A + RET + +LF70F: XOR A + CALL LF467 + LD C,A + LD A,(01094H) + LD B,A +LF718: LD HL,0E678H +LF71B: IN A,(0FEH) + AND 00DH + CP C + RET Z + + DEC HL + LD A,H + OR L + NOP + NOP + JR NZ,LF71B ; (-00dH) + DJNZ LF718 ; (-012H) + XOR A + LD (0108FH),A + CALL LF705 +LF731: LD A,041H + JP LF501 +LF736: INC HL +LF737: LD A,(HL) + CP 020H + JR Z,LF736 ; (-006H) + EX (SP),HL + CP (HL) + INC HL + EX (SP),HL + RET NZ + + INC HL + RET + +LF743: PUSH BC + LD C,0EBH + LD B,H + OUT (C),L + OUT (0EAH),A + POP BC + OR A + RET + +LF74E: PUSH BC + LD C,0EBH + LD B,H + OUT (C),L + IN A,(0EAH) + POP BC + OR A + RET + + LD A,E + CALL LF743 + INC HL + LD A,D + CALL LF743 + DEC HL + RET + +LF764: CALL LF74E + LD E,A + INC HL + CALL LF74E + LD D,A + DEC HL + RET + +LF76F: CALL LF737 + INC H + JR Z,LF79F ; (+02aH) + LD DE,00000H +LF778: CALL LF7CA + SUB 030H + CP 00AH + RET NC + + INC HL + PUSH HL + LD H,D + LD L,E + ADD HL,HL + JR C,LF79A ; (+013H) + ADD HL,HL + JR C,LF79A ; (+010H) + ADD HL,DE + JR C,LF79A ; (+00dH) + ADD HL,HL + JR C,LF79A ; (+00aH) + LD E,A + LD D,000H + ADD HL,DE + JR C,LF79A ; (+004H) + EX DE,HL + POP HL + JR LF778 ; (-022H) +LF79A: LD A,002H + JP LF501 +LF79F: LD DE,00000H +LF7A2: LD A,(HL) + CALL LF7BA + RET C + + INC HL + EX DE,HL + ADD HL,HL + JR C,LF79A ; (-012H) + ADD HL,HL + JR C,LF79A ; (-015H) + ADD HL,HL + JR C,LF79A ; (-018H) + ADD HL,HL + JR C,LF79A ; (-01bH) + ADD A,L + LD L,A + EX DE,HL + JR LF7A2 ; (-018H) +LF7BA: SUB 030H + CP 00AH + CCF + RET NC + + SUB 011H + CP 006H + CCF + RET C + + ADD A,00AH + RET + +LF7C9: INC HL +LF7CA: LD A,(HL) + CP 020H + JR Z,LF7C9 ; (-006H) + RET + +LF7D0: LD (011ACH),A + LD HL,08000H + LD (011AAH),HL + LD A,(01092H) + AND 012H + LD A,03BH + JP Z,LF501 + CALL BRKEY + JR Z,LF825 ; (+03dH) + LD A,009H + CALL LF62F + LD C,019H +LF7EF: CALL LF8B1 + LD A,(0136BH) + LD B,A +LF7F6: PUSH BC + CALL LF857 + POP BC + DJNZ LF7F6 ; (-007H) + CALL BRKEY + JR Z,LF825 ; (+023H) + LD B,007H + LD A,(0136BH) + LD E,A + LD D,000H +LF80A: ADD HL,DE + DJNZ LF80A ; (-003H) + DEC C + JR NZ,LF7EF ; (-021H) +LF810: CALL LF8F1 + DEC B + ADD HL,BC + ADD HL,BC + DEC BC + LD A,(BC) + DEC C + LD A,(01092H) + BIT 4,A + RET Z + + LD A,01AH + CALL LF62F + RET + +LF825: LD A,001H + LD (013D9H),A + LD SP,012A8H + JR LF810 ; (-01fH) +LF82F: LD D,000H + LD BC,(0109DH) +LF835: RRC C + LD A,C + RET C + + AND B + JR Z,LF835 ; (-007H) + OUT (0CDH),A + LD A,(HL) + OR D + LD D,A + JR LF835 ; (-00eH) +LF843: PUSH HL + XOR A + LD HL,01098H + BIT 2,(HL) + JR NZ,LF855 ; (+009H) + INC A + LD HL,011ACH + BIT 0,(HL) + JR Z,LF855 ; (+001H) + INC A +LF855: POP HL + RET + +LF857: LD B,008H + LD DE,011B4H + PUSH DE + IN A,(0E0H) + OUT (0E0H),A + PUSH HL +LF862: PUSH BC + PUSH DE + CALL LF82F + LD A,(0136BH) + LD E,A + LD A,D + LD D,000H + ADD HL,DE + POP DE + LD (DE),A + INC DE + POP BC + DJNZ LF862 ; (-013H) + POP HL + INC HL + IN A,(0E1H) + POP DE + PUSH HL + EX DE,HL + LD DE,011C4H + PUSH DE + LD C,008H +LF882: LD B,008H + PUSH HL +LF885: RRC (HL) + RRA + INC HL + DJNZ LF885 ; (-006H) + LD (DE),A + INC DE + EX AF,AF' + CALL LF843 + CP 002H + JR NZ,LF898 ; (+003H) + EX AF,AF' + LD (DE),A + INC DE +LF898: POP HL + DEC C + JR NZ,LF882 ; (-01aH) + POP HL + LD B,008H + CALL LF843 + CP 002H + JR NZ,LF8A8 ; (+002H) + SLA B +LF8A8: LD A,(HL) + CALL LF8D6 + INC HL + DJNZ LF8A8 ; (-007H) + POP HL + RET + +LF8B1: CALL LF843 + LD DE,(0136DH) + EX AF,AF' + CALL LF8F1 + INC BC + ADD HL,BC + ADD HL,BC + ADD HL,BC + EX AF,AF' + CP 002H + JR NZ,LF8C9 ; (+004H) + SLA E + RL D +LF8C9: LD A,00BH + CALL LF62F + CALL LF62F + LD A,E + CALL LF8D6 + LD A,D +LF8D6: PUSH HL + LD HL,012AEH + LD (HL),A + CALL LF8E3 + CALL LF8E3 + POP HL + RET + +LF8E3: XOR A + RLD + ADD A,030H + CP 03AH + JR C,LF8EE ; (+002H) + ADD A,007H +LF8EE: JP LF62F +LF8F1: EX (SP),HL + PUSH BC + LD B,(HL) + INC HL +LF8F5: LD A,(HL) + INC HL + CALL LF62F + DJNZ LF8F5 ; (-007H) + POP BC + EX (SP),HL + RET + +LF8FF: CALL LF467 + LD HL,01366H +LF905: LD (HL),A + INC HL + LD (HL),E + INC HL + LD (HL),D + LD HL,TF949 + LD B,006H + CALL LF940 + LD HL,0A8C1H + CALL LF92D + LD HL,TF955 + LD B,003H + CALL LF940 + LD HL,0A8C0H + CALL LF92D + LD HL,TF95B + LD B,003H + JR LF940 ; (+013H) +LF92D: LD C,0D7H + LD A,080H + OUT (C),A + DEC C + IN E,(C) + IN D,(C) + OR A + PUSH HL + SBC HL,DE + POP HL + JR NZ,LF92D ; (-012H) + RET + +LF940: LD A,(HL) + INC HL + LD C,(HL) + INC HL + OUT (C),A + DJNZ LF940 ; (-008H) + RET + +TF949: DB 0b4H, 0d7H, 0c1H, 0d6H, 0a8H, 0d6H, 074H, 0d7H, 002H, 0d5H, 000H, 0d5H +TF955: DB 0b4H, 0d7H, 0c0H, 0d6H, 0a8H, 0d6H +TF95B: DB 074H, 0d7H, 0f6H, 0d5H, 079H, 0d5H + +LF961: PUSH IX + PUSH BC + PUSH HL + PUSH HL + POP IX + JR LF972 ; (+008H) +LF96A: PUSH IX + PUSH BC + PUSH HL + LD IX,01366H +LF972: LD C,0D7H + LD A,080H + OUT (C),A + LD A,040H + OUT (C),A + DEC C + IN E,(C) + IN D,(C) + DEC C + IN A,(C) + IN B,(C) + LD C,A + PUSH BC + LD A,D + OR E + JR NZ,LF98F ; (+003H) + LD DE,0A8C0H +LF98F: LD HL,0A8C0H + LD A,(IX+000H) + OR A + SBC HL,DE + LD DE,05460H + CALL LF9D2 + OR A + LD E,(IX+001H) + LD D,(IX+002H) + RR D + RR E + PUSH AF + ADD HL,DE + LD DE,05460H + CALL LF9D2 + LD C,A + ADD HL,HL + EX DE,HL + POP AF + LD A,C + POP BC + PUSH AF + OR A + LD HL,03CFBH + SBC HL,BC + JR C,LF9C1 ; (+001H) + INC DE +LF9C1: POP AF + JR NC,LF9C5 ; (+001H) + INC DE +LF9C5: EX DE,HL + LD DE,0A8C0H + CALL LF9D2 + EX DE,HL + POP HL + POP BC + POP IX + RET + +LF9D2: OR A + SBC HL,DE + JR NC,LF9D9 ; (+002H) + ADD HL,DE + RET + +LF9D9: XOR 001H + RET + +LF9DC: CALL LF467 + DEC A + JP M,LF9F0 + CALL LF9FF + LD HL,TFA1D +LF9E9: AND 00FH + CALL LF44C + LD A,(HL) + RET + +LF9F0: LD A,0F7H + CALL LFA15 + CPL + AND 03CH + RRCA + RRCA + LD HL,TFA2D + JR LF9E9 ; (-016H) +LF9FF: PUSH AF + LD A,0CFH + OUT (0D0H),A + POP AF + CP 002H + JR C,LFA0B ; (+002H) + SUB 002H +LFA0B: LD C,0F0H + DEC A + JP M,LFA12 + INC C +LFA12: IN A,(C) + RET + +LFA15: LD C,0D0H + OUT (C),A + INC C + IN A,(C) + RET + +TFA1D: DB 000H, 005H, 001H, 000H, 003H, 004H, 002H, 003H, 007H, 006H, 008H, 007H, 000H, 005H, 001H, 000H +TFA2D: DB 000H, 007H, 003H, 000H, 005H, 006H, 004H, 005H, 001H, 008H, 002H, 001H, 000H, 007H, 003H, 000H + +LFA3D: CALL LF467 + DEC A + JP M,LFA58 + PUSH AF + CALL LF9FF + CPL + POP BC + DEC B + DEC B + LD B,010H + JP M,LFA53 + LD B,020H +LFA53: AND B +LFA54: RET Z + + LD A,001H + RET + +LFA58: LD A,0F6H + CALL LFA15 + CPL + AND 010H + JR LFA54 ; (-00eH) +LFA62: LD D,A + XOR A + LD C,A + LD B,00EH +LFA67: LD HL,0E678H +LFA6A: IN A,(0FEH) + AND 00DH + CP C + JR Z,LFA7D ; (+00cH) + DEC HL + LD A,H + OR L + NOP + NOP + JR NZ,LFA6A ; (-00eH) + DJNZ LFA67 ; (-013H) + LD A,0FFH + RET + +LFA7D: LD A,D + OUT (0FFH),A + LD A,080H + OUT (0FEH),A +LFA84: IN A,(0FEH) + AND 00DH + CP 001H + JR NZ,LFA84 ; (-008H) + XOR A + OUT (0FEH),A + RET + +LFA90: LD HL,TFAA9 + LD B,004H + CALL LF940 + LD C,D + LD B,000H +LFA9B: EX (SP),HL + DJNZ LFA9B ; (-003H) + DEC C + JR NZ,LFA9B ; (-006H) + LD HL,TFAB1 + LD B,002H + JP LF940 + +TFAA9: DB 036H + DB 0D7H + DB 001H + DB 0D3H + DB 0F9H + DB 0D4H + DB 003H + DB 0D4H +TFAB1: DB 036H + DB 0D7H + DB 000H + DB 0D3H + + ALIGN_NOPS 0FDA0H + + DB 053H + DB 005H + DB 059H + DB 04EH + DB 054H + DB 041H + DB 0D8H + DB 04FH + DB 005H + DB 056H + DB 045H + DB 052H + DB 020H + DB 046H + DB 04CH + DB 04FH + DB 0D7H + DB 049H + DB 005H + DB 04CH + DB 04CH + DB 045H + DB 047H + DB 041H + DB 04CH + DB 020H + DB 044H + DB 041H + DB 054H + DB 0C1H + DB 054H + DB 005H + DB 059H + DB 050H + DB 045H + DB 020H + DB 04DH + DB 049H + DB 053H + DB 04DH + DB 041H + DB 054H + DB 043H + DB 0C8H + DB 053H + DB 005H + DB 054H + DB 052H + DB 049H + DB 04EH + DB 047H + DB 020H + DB 04CH + DB 045H + DB 04EH + DB 047H + DB 054H + DB 0C8H + DB 04DH + DB 005H + DB 045H + DB 04DH + DB 04FH + DB 052H + DB 059H + DB 020H + DB 043H + DB 041H + DB 050H + DB 041H + DB 043H + DB 049H + DB 054H + DB 0D9H + DB 041H + DB 005H + DB 052H + DB 052H + DB 041H + DB 059H + DB 020H + DB 044H + DB 045H + DB 046H + DB 0AEH + DB 04CH + DB 005H + DB 049H + DB 04EH + DB 045H + DB 04CH + DB 045H + DB 04EH + DB 047H + DB 054H + DB 0C8H + DB 080H + DB 047H + DB 04FH + DB 053H + DB 055H + DB 042H + DB 020H + DB 005H + DB 04EH + DB 045H + DB 053H + DB 054H + DB 049H + DB 04EH + DB 0C7H + DB 046H + DB 04FH + DB 052H + DB 02DH + DB 04EH + DB 045H + DB 058H + DB 0D4H + DB 044H + DB 045H + DB 046H + DB 020H + DB 046H + DB 04EH + DB 020H + DB 005H + DB 04EH + DB 045H + DB 053H + DB 054H + DB 049H + DB 04EH + DB 0C7H + DB 04EH + DB 045H + DB 058H + DB 0D4H + DB 052H + DB 045H + DB 054H + DB 055H + DB 052H + DB 0CEH + DB 055H + DB 005H + DB 04EH + DB 020H + DB 044H + DB 045H + DB 046H + DB 02EH + DB 020H + DB 046H + DB 055H + DB 04EH + DB 043H + DB 054H + DB 049H + DB 04FH + DB 0CEH + DB 055H + DB 005H + DB 04EH + DB 020H + DB 044H + DB 045H + DB 046H + DB 02EH + DB 020H + DB 04CH + DB 049H + DB 04EH + DB 0C5H + DB 043H + DB 005H + DB 041H + DB 04EH + DB 027H + DB 054H + DB 020H + DB 006H + DB 043H + DB 04FH + DB 04EH + DB 0D4H + DB 04DH + DB 005H + DB 045H + DB 04DH + DB 04FH + DB 052H + DB 059H + DB 020H + DB 050H + DB 052H + DB 04FH + DB 054H + DB 045H + DB 043H + DB 054H + DB 049H + DB 04FH + DB 0CEH + DB 049H + DB 005H + DB 04EH + DB 053H + DB 054H + DB 052H + DB 055H + DB 043H + DB 054H + DB 049H + DB 04FH + DB 0CEH + DB 043H + DB 005H + DB 041H + DB 04EH + DB 027H + DB 054H + DB 020H + DB 006H + DB 052H + DB 045H + DB 053H + DB 055H + DB 04DH + DB 0C5H + DB 052H + DB 045H + DB 053H + DB 055H + DB 04DH + DB 0C5H + DB 050H + DB 041H + DB 0CCH + DB 080H + DB 052H + DB 045H + DB 041H + DB 0C4H + DB 053H + DB 057H + DB 041H + DB 050H + DB 020H + DB 005H + DB 04CH + DB 045H + DB 056H + DB 045H + DB 0CCH + DB 080H + DB 080H + DB 053H + DB 005H + DB 059H + DB 053H + DB 054H + DB 045H + DB 04DH + DB 020H + DB 049H + DB 0C4H + DB 046H + DB 005H + DB 052H + DB 041H + DB 04DH + DB 049H + DB 04EH + DB 0C7H + DB 04FH + DB 005H + DB 056H + DB 045H + DB 052H + DB 052H + DB 055H + DB 0CEH + DB 050H + DB 005H + DB 041H + DB 052H + DB 049H + DB 054H + DB 0D9H + DB 080H + DB 080H + DB 080H + DB 080H + DB 080H + DB 080H + DB 080H + DB 080H + DB 046H + DB 005H + DB 049H + DB 04CH + DB 045H + DB 020H + DB 04EH + DB 04FH + DB 054H + DB 020H + DB 046H + DB 04FH + DB 055H + DB 04EH + DB 0C4H + DB 048H + DB 005H + DB 041H + DB 052H + DB 044H + DB 057H + DB 041H + DB 052H + DB 0C5H + DB 041H + DB 005H + DB 04CH + DB 052H + DB 045H + DB 041H + DB 044H + DB 059H + DB 020H + DB 045H + DB 058H + DB 049H + DB 053H + DB 0D4H + DB 041H + DB 005H + DB 04CH + DB 052H + DB 045H + DB 041H + DB 044H + DB 059H + DB 020H + DB 04FH + DB 050H + DB 045H + DB 0CEH + DB 04EH + DB 005H + DB 04FH + DB 054H + DB 020H + DB 04FH + DB 050H + DB 045H + DB 0CEH + DB 080H + DB 057H + DB 005H + DB 052H + DB 049H + DB 054H + DB 045H + DB 020H + DB 050H + DB 052H + DB 04FH + DB 054H + DB 045H + DB 043H + DB 0D4H + DB 080H + DB 080H + DB 080H + DB 04EH + DB 005H + DB 04FH + DB 054H + DB 020H + DB 052H + DB 045H + DB 041H + DB 044H + DB 0D9H + DB 054H + DB 005H + DB 04FH + DB 04FH + DB 020H + DB 04DH + DB 041H + DB 04EH + DB 059H + DB 020H + DB 046H + DB 049H + DB 04CH + DB 045H + DB 0D3H + DB 044H + DB 005H + DB 049H + DB 053H + DB 04BH + DB 020H + DB 04DH + DB 049H + DB 053H + DB 04DH + DB 041H + DB 054H + DB 043H + DB 0C8H + DB 04EH + DB 005H + DB 04FH + DB 020H + DB 046H + DB 049H + DB 04CH + DB 045H + DB 020H + DB 053H + DB 050H + DB 041H + DB 043H + DB 0C5H + DB 055H + DB 005H + DB 04EH + DB 046H + DB 04FH + DB 052H + DB 04DH + DB 041H + DB 0D4H + DB 054H + DB 005H + DB 04FH + DB 04FH + DB 020H + DB 04CH + DB 04FH + DB 04EH + DB 047H + DB 020H + DB 046H + DB 049H + DB 04CH + DB 0C5H + DB 080H + DB 080H + DB 044H + DB 005H + DB 045H + DB 056H + DB 02EH + DB 020H + DB 04EH + DB 041H + DB 04DH + DB 0C5H + DB 043H + DB 005H + DB 041H + DB 04EH + DB 027H + DB 054H + DB 020H + DB 045H + DB 058H + DB 045H + DB 043H + DB 055H + DB 054H + DB 0C5H + DB 049H + DB 005H + DB 04CH + DB 04CH + DB 045H + DB 047H + DB 041H + DB 04CH + DB 020H + DB 046H + DB 049H + DB 04CH + DB 045H + DB 04EH + DB 041H + DB 04DH + DB 0C5H + DB 049H + DB 005H + DB 04CH + DB 04CH + DB 045H + DB 047H + DB 041H + DB 04CH + DB 020H + DB 046H + DB 049H + DB 04CH + DB 045H + DB 04DH + DB 04FH + DB 044H + DB 0C5H + DB 080H + DB 04FH + DB 005H + DB 055H + DB 054H + DB 020H + DB 04FH + DB 046H + DB 020H + DB 046H + DB 049H + DB 04CH + DB 0C5H + DB 04CH + DB 005H + DB 04FH + DB 047H + DB 049H + DB 043H + DB 041H + DB 04CH + DB 020H + DB 04EH + DB 055H + DB 04DH + DB 042H + DB 045H + DB 0D2H + DB 04CH + DB 050H + DB 054H + DB 03AH + DB 04EH + DB 005H + DB 04FH + DB 054H + DB 020H + DB 052H + DB 045H + DB 041H + DB 044H + DB 0D9H + DB 080H + DB 080H + DB 044H + DB 005H + DB 045H + DB 056H + DB 02EH + DB 020H + DB 04DH + DB 04FH + DB 044H + DB 0C5H + DB 055H + DB 005H + DB 04EH + DB 050H + DB 052H + DB 049H + DB 04EH + DB 054H + DB 041H + DB 042H + DB 04CH + DB 0C5H + DB 043H + DB 005H + DB 048H + DB 045H + DB 043H + DB 04BH + DB 020H + DB 053H + DB 055H + DB 0CDH + DB 000H + DB 000H + DB 000H + DB 000H + +VERSION: DB 020H + DB 038H + DB 034H + DB 02EH + DB 031H + DB 030H + DB 02EH + DB 030H + DB 038H + DB 020H + DB 056H + DB 031H + DB 02EH + DB 030H + DB 043H + DB 020H diff --git a/software/roms/9Z_504M.ROM b/software/roms/9Z_504M.ROM new file mode 100644 index 0000000000000000000000000000000000000000..1086ec39c09bbfa219ccc382d130096daf1f6359 GIT binary patch literal 8192 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 OnZt!QJi5%`!T$@nA#K$F literal 0 HcmV?d00001 diff --git a/software/roms/MZ800_1Z_013B.ORI b/software/roms/MZ800_1Z_013B.ORI new file mode 100644 index 0000000000000000000000000000000000000000..68245881434f3fc270b247d4381fc6acf356301d GIT binary patch literal 4096 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 H-0}Ve7I}+f literal 0 HcmV?d00001 diff --git a/software/roms/MZ800_1Z_013B.rom b/software/roms/MZ800_1Z_013B.rom new file mode 100644 index 0000000000000000000000000000000000000000..68245881434f3fc270b247d4381fc6acf356301d GIT binary patch literal 4096 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 H-0}Ve7I}+f literal 0 HcmV?d00001 diff --git a/software/roms/MZ800_9Z_504M.ORI b/software/roms/MZ800_9Z_504M.ORI new file mode 100644 index 0000000000000000000000000000000000000000..1086ec39c09bbfa219ccc382d130096daf1f6359 GIT binary patch literal 8192 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 OnZt!QJi5%`!T$@nA#K$F literal 0 HcmV?d00001 diff --git a/software/roms/MZ800_9Z_504M.rom b/software/roms/MZ800_9Z_504M.rom new file mode 100644 index 0000000000000000000000000000000000000000..289ab6db724a6022f4ae267372455210b4b75c08 GIT binary patch literal 5120 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 RGg``d_`?4){r_KG{|C>>beaGF literal 0 HcmV?d00001 diff --git a/software/roms/MZ800_CGROM.ORI b/software/roms/MZ800_CGROM.ORI new file mode 100644 index 0000000000000000000000000000000000000000..72bf0dc9120a97727903ee21eee9a06049410638 GIT binary patch literal 4096 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 E0-UXq>Hq)$ literal 0 HcmV?d00001 diff --git a/software/roms/MZ800_IOCS.ORI b/software/roms/MZ800_IOCS.ORI new file mode 100644 index 0000000000000000000000000000000000000000..09c0605046d53486d29375741af729298762e56b GIT binary patch literal 3072 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 ## ## History: August 2018 - Initial script written. +## March 2021 - Added MZ-800 IPL ## ######################################################################################################### ## This source file is free software: you can redistribute it and#or modify @@ -32,7 +33,7 @@ ROOTDIR=../../tranZPUter TOOLDIR=${ROOTDIR}/software/tools JARDIR=${ROOTDIR}/software/tools ASM=glass-0.5.jar -BUILDROMLIST="MZ80AFI monitor_SA1510 monitor_80c_SA1510 monitor_1Z-013A monitor_80c_1Z-013A monitor_1Z-013A-KM monitor_80c_1Z-013A-KM MZ80B_IPL" +BUILDROMLIST="MZ800_1Z_013B MZ800_9Z_504M MZ800_IOCS MZ80AFI monitor_SA1510 monitor_80c_SA1510 monitor_1Z-013A monitor_80c_1Z-013A monitor_1Z-013A-KM monitor_80c_1Z-013A-KM MZ80B_IPL" #BUILDMZFLIST="hi-ramcheck sharpmz-test" BUILDMZFLIST="BASIC sharpmz-test" ASMDIR=${ROOTDIR}/software/asm @@ -65,3 +66,6 @@ do fi fi done + +# Manual tinkering to build the MZ800 Rom. +cat ${ROMDIR}/MZ800_1Z_013B.rom ${ROMDIR}/MZ800_CGROM.ORI ${ROMDIR}/MZ800_9Z_504M.rom ${ROMDIR}/MZ800_IOCS.rom > ${ROMDIR}/MZ800_IPL.rom