11 Commits

Author SHA1 Message Date
Philip Smart
78fddfb2eb Fix build.sh: remove set -e and broken symlink target
Remove set -e since we track pass/fail explicitly and return the
appropriate exit code at the end. Remove mz2000_mon_1z001m from the
ROM build list as it depends on a symlink to an external path that
doesn't exist in the repository.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 15:50:29 +00:00
Philip Smart
066e049538 Add Z80 assembly sources, ROMs and build tools to repository
Un-ignore software/asm/, software/tools/, and software/roms/ so that
CI/CD builds on Jenkins can assemble Z80 ROMs, TZFS, and CP/M from
source. Previously these files were only available on the dev machine.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 15:42:50 +00:00
Philip Smart
e3771cdf9c Add global build script and VERSION file
Add build.sh for building all FusionX components: Z80 assembly ROMs,
TZFS ROMs, CP/M variants, kernel modules, user-space apps, and CPLD
bitstreams. Supports selective builds via --asm/--tzfs/--cpm/--drivers/
--cpld flags. Updated rebuilt binaries from build verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 15:06:30 +00:00
Philip Smart
0a0ed14c6c Merge remote-tracking branch 'origin/master' 2026-03-14 15:05:21 +00:00
eaw
9baeec811b Update README from eaw.app website content 2026-03-14 10:07:20 +00:00
Philip Smart
75fb464b4d Bug fix in RFS 2023-11-08 16:07:03 +00:00
Philip Smart
dcb308f0df MZ700 and MZ1500 updates 2023-07-14 22:12:50 +01:00
Philip Smart
5fa8d1fada Adding MZ-1500 host 2023-05-24 09:12:39 +01:00
Philip Smart
462052140e Update to readme 2023-05-10 10:06:42 +01:00
Philip Smart
5d0daa838e Update to readme 2023-05-10 10:05:32 +01:00
Philip Smart
1ff4b558a5 Updates and added terminal driver for MZ-2000 2023-05-10 09:52:17 +01:00
111 changed files with 103029 additions and 1475 deletions

21
.gitignore vendored
View File

@@ -1743,3 +1743,24 @@ software/FusionX/src/z80drv/src/z80driver.c.bad
software/FusionX/src/z80drv/src/z80vhw_rfs.c.bad
CPLD/v1.0/MZ2000.old/
# Un-ignore files needed for CI/CD builds
!software/asm/
!software/asm/*.asm
!software/asm/include/
!software/asm/include/*.asm
!software/tools/
!software/tools/assemble_*.sh
!software/tools/copytosd.sh
!software/tools/make_cpmdisks.sh
!software/tools/glass*.jar
!software/tools/dz80
!software/tools/dz80_v20
!software/tools/nasconv
!software/tools/mzftool.pl
!software/tools/flashmmcfg
!software/tmp/
!software/roms/
!software/roms/*.rom
!software/roms/*.bin
!software/roms/*.BIN
!software/roms/*.ori

572
README.md vendored
View File

@@ -1,4 +1,10 @@
<img src='http://eaw.app/images/FusionX_Wired.png' height='70%' width='70%' style="margin-left: auto; margin-right: auto; display: block;"/>
# tzpuFusionX
**Website:** [engineers@work](https://eaw.app) | **Repository:** [git.eaw.app/eaw/tzpuFusionX](https://git.eaw.app/eaw/tzpuFusionX)
---
<img src='../images/FusionX_Wired.png' height='70%' width='70%' style="margin-left: auto; margin-right: auto; display: block;"/>
## <font style="color: yellow;" size="6">Overview</font>
@@ -7,7 +13,7 @@ The tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> is a spinoff concept from the tra
rapid application loading from SD card and by using a daughter board, better graphics and sound.
<div style="padding-top: 0.8em;"></div>
The <i>FusionX</i> board can also be used to power alternative CPU's on the host for testing, development and to provide a completely different software platform and applications. It can use the underlying hosts keyboard, monitor, I/O and additionally better graphics and sound provided by the <i>FusionX</i>.
The <i>FusionX</i> board can also be used to power alternative CPUs on the host for testing, development and to provide a completely different software platform and applications. It can use the underlying hosts keyboard, monitor, I/O and additionally better graphics and sound provided by the <i>FusionX</i>.
<div style="padding-top: 0.8em;"></div>
It shares similarities with the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup> but instead of realising it in hardware via an FPGA it realises
@@ -18,7 +24,7 @@ Using the same base design as the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup> it i
<div style="padding-top: 0.8em;"></div>
In Z80 configuration, a Linux Kernel driver instantiates a Z80 emulation which realises a Z80 CPU in software which in turn can command and control the host system. The kernel driver along with a controlling application
can provide a wealth of features to the host through this mechanism. The SOM is also connected to an SD Drive and USB 2.0 port so there is no limit to features which can be proivded.
can provide a wealth of features to the host through this mechanism. The SOM is also connected to an SD Drive and USB 2.0 port so there is no limit to features which can be provided.
<div style="padding-top: 0.8em;"></div>
Like the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup>, the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> can provide enhanced video and sound to the host. The SOM incorporates dual DAC audio and a 2D GPU with configurable resolutions switched onto the hosts video and audio outputs under software control.
@@ -27,8 +33,8 @@ Like the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup>, the tran<i>ZPU</i>ter<sup><i
The <i>FusionX</i> board is ideal for any developer wanting to physically program and interact with retro hardware using a Linux platform with Wifi and USB/Serial port connectivity.
<div style="padding-top: 0.8em;"></div>
To most retro users, in the early stages of <i>FusionX</i> development, the board wont have much use. As the project matures, a board can be obtained and installed into the Z80 socket of their Sharp or simlar Z80 based system (providing there is sufficient room to accommodate this board) and utilise the upgraded featues, such as:
<ul style="line-height: 0.9em;"><font size="3">
To most retro users, in the early stages of <i>FusionX</i> development, the board won't have much use. As the project matures, a board can be obtained and installed into the Z80 socket of their Sharp or similar Z80 based system (providing there is sufficient room to accommodate this board) and utilise the upgraded features, such as:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">Original host specifications</font><br>- the machine behaves just as though it had a physical Z80 within. There might be slight differences in the Z80 functionality as it is implemented in software but the Z80 hardware timing is accurate.</li>
<li><font style="color: orange;" size="3">Accelerator</font><br>- the Z80 can run at much higher speeds due to the abundance of memory and 1.2GHz dual-core processor, which would typically see performance upto that of a 500MHz Z80.</li>
<li><font style="color: orange;" size="3">Emulation</font><br>- emulation of all the Sharp MZ series machines, experiencing it through the host system keyboard, monitor and I/O.</li>
@@ -82,13 +88,13 @@ thus the CPLD is able to drive 5V circuitry and with sufficient drive current, 2
The CPLD internal state machines are clocked by an external 50MHz oscillator, this allows for adequate sampling and state change for a typical 1MHz - 6MHz Z80 host.
</div>
![FusionX Schematic2](http://eaw.app/images/tzpuFusionX_v1_0_Schematics-2.png)
![FusionX Schematic2](../images/tzpuFusionX_v1_0_Schematics-2.png)
<font style="color: cyan;" size="4">Schematic 2 - I/O (Audio, UART, USB)</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The SOM is rich in peripherals and this circuit interfaces some of them for use in the FusionX, these include:
<ul style="line-height: 0.9em;"><font size="3">
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">Stereo Audio Microphone input</font><br>- a digital microphone input is also available but the pins are used in the CPLD interface.</li>
<li><font style="color: orange;" size="3">Stereo Audio DAC output</font><br>- dual digital to analogue converters for sound output which can be clocked at 48KHz.</li>
<li><font style="color: orange;" size="3">WiFi Antenna</font><br>- a SSW101B 20/40MHz IEEE 802.11 b/g/n/e/l/n/w WiFi transceiver operating in the 2.4GHz band with a 500M range. The SOM also includes a 100MHz ETH PHY but this is not used in this design as hard wired ethernet is not practical for a board which is
@@ -97,12 +103,12 @@ sited inside a retro machine.</li>
<li><font style="color: orange;" size="3">USB</font><br>- a Linux connected USB port allowing for device expansion, such as additional storage, mice etc.</li>
<li><font style="color: orange;" size="3">Fast UART</font><br>- high speed full duplex with hardware handshake UART.</li>
<li><font style="color: orange;" size="3">UART</font><br>- standard 2 pin UART operating upto 500KHz.</li>
<li><font style="color: orange;" size="3">SD Card</font><br>- the SOM has inbuilt FlashNAND so can accomodate a simple Linux filesystem, addition of an SD card allows for greater storage of Host applications and Linux utilities. An SD card also makes for ease of upgrades as the SOM will auto upgrade when a suitably prepared SD card is present on boot.</li>
<li><font style="color: orange;" size="3">SD Card</font><br>- the SOM has inbuilt FlashNAND so can accommodate a simple Linux filesystem, addition of an SD card allows for greater storage of Host applications and Linux utilities. An SD card also makes for ease of upgrades as the SOM will auto upgrade when a suitably prepared SD card is present on boot.</li>
</font></ul>
</div>
![FusionX Schematic2](http://eaw.app/images/tzpuFusionX_v1_0_Schematics-3.png)
![FusionX Schematic2](../images/tzpuFusionX_v1_0_Schematics-3.png)
<font style="color: cyan;" size="4">Schematic 3 - Video (VideoDAC, Contrast DAC)</font>
@@ -117,7 +123,7 @@ DAC, as it is sending the video signal with colour information as a voltage cont
In order to get true black, the CPLD creates a blanking signal, MONO.BLANK, which is paired with a MUX 0V clamp on the daughter board which drives the monochrome monitor, this sees the RGB332 as 0V when 00000000 is present, then varying between 4.01V-5V when non-zero.
</div>
![FusionX Schematic4](http://eaw.app/images/tzpuFusionX_v1_0_Schematics-4.png)
![FusionX Schematic4](../images/tzpuFusionX_v1_0_Schematics-4.png)
<font style="color: cyan;" size="4">Schematic 4 - Power Supply (3.3V, USB)</font>
@@ -128,7 +134,7 @@ The power supply, for the SOM and CPLD, converts the 5V present on the Z80 socke
Additionally, a software controlled USB power switch is installed to enable (and reset if required) +5V power to the USB expansion port.
</div>
![FusionX Schematic5](http://eaw.app/images/tzpuFusionX_v1_0_Schematics-5.png)
![FusionX Schematic5](../images/tzpuFusionX_v1_0_Schematics-5.png)
<font style="color: cyan;" size="4">Schematic 5 - CPLD Interface</font>
@@ -136,70 +142,490 @@ Additionally, a software controlled USB power switch is installed to enable (and
The final schematic is the interface between the SOM and the CPLD. Originally this was going to be a bi-directional 16bit bus with Read/Write and Strobe signals but after testing, the setup time for a 16bit signal with tri-state switching was much slower than an SPI connection
due to the GPIO register layout and operation within the SOM and the speed of the I/O operations within the SOM.
<div style="padding-top: 0.8em;"></div>
The solution used is to have a bidirectional 72MHz SPI bus between the SOM and CPLD for transmitting Z80 transaction requests and an 8bit read only parallel bus for more rapid reading of Z80 Data and seperate Z80 state information.
The solution used is to have a bidirectional 72MHz SPI bus between the SOM and CPLD for transmitting Z80 transaction requests and an 8bit read only parallel bus for more rapid reading of Z80 Data and separate Z80 state information.
</div>
![FusionX Schematic6](http://eaw.app/images/tzpuFusionX_v1_0_Schematics-6.png)
![FusionX Schematic6](../images/tzpuFusionX_v1_0_Schematics-6.png)
#### <font style="color: yellow;" size="5">PCB
#### <font style="color: yellow;" size="5">PCB</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The PCB was designed with minimum size as a primary requirement for the various machines in which it would be installed. It also had to be compatible with the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup> for interchangeability.
<div style="padding-top: 0.8em;"></div>
A major concern was heat dissipation as the PCB, when installed within an MZ-700 is very close to existing motherboard components which give off a lot of heat with no air circulation in a sealed compact housing. This meant active components couldnt be sited on the PCB underside
A major concern was heat dissipation as the PCB, when installed within an MZ-700 is very close to existing motherboard components which give off a lot of heat with no air circulation in a sealed compact housing. This meant active components couldn't be sited on the PCB underside
as heat generation would lead to instability and failure, which in turn led to an increase in the final PCB size.
<div style="padding-top: 0.8em;"></div>
The smallest components which could be manually assembled where used, ie. 0402/0603 passive devices and 0.5mm IC pitch spacing to reduce overall size and a 4 layer stackup selected to fit all required components.
The smallest components which could be manually assembled were used, ie. 0402/0603 passive devices and 0.5mm IC pitch spacing to reduce overall size and a 4 layer stackup selected to fit all required components.
<div style="padding-top: 0.8em;"></div>
</div>
<font style="color: cyan;" size="4">PCB Top Overview</font>
![FusionX PCB Top](http://eaw.app/images/tzpuFusionX_v1_0_3D_Top.png)
![FusionX PCB Top](../images/tzpuFusionX_v1_0_3D_Top.png)
<font style="color: cyan;" size="4">PCB Bottom Overview</font>
![FusionX PCB Bottom](http://eaw.app/images/tzpuFusionX_v1_0_3D_Bottom.png)
![FusionX PCB Bottom](../images/tzpuFusionX_v1_0_3D_Bottom.png)
<font style="color: cyan;" size="4">PCB 4 Layer Routing Overview</font>
![FusionX Routing](http://eaw.app/images/tzpuFusionX_v1_0_layout.png)
![FusionX Routing](../images/tzpuFusionX_v1_0_layout.png)
<font style="color: cyan;" size="4">PCB Assembled</font>
![FusionX Assembled](http://eaw.app/images/FusionX_Top.png)
![FusionX Assembled](../images/FusionX_Top.png)
![FusionX Assembled](http://eaw.app/images/FusionX_Bottom.png)
![FusionX Assembled](../images/FusionX_Bottom.png)
<font style="color: cyan;" size="4">PCB Component Placement and Bill of Materials</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
Click <a href="http://eaw.app/_pages/FusionX_v1_0_BOM.html">here</a> to view an interactive PCB component placement diagram and Bill of Materials.
Click <a href="../_pages/FusionX_v1_0_BOM.html">here</a> to view an interactive PCB component placement diagram and Bill of Materials.
</div>
--------------------------------------------------------------------------------------------------------
<a name="cpld" id="cpld"></a>
###### <font style="color: yellow;" size="5">CPLD</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> uses an Altera MAX7000AE CPLD — specifically the <b>EPM7512AETC144-10</b> — as the central interface between the SOM and the host Z80 socket. This is a 512-macrocell, 144-pin TQFP device operating at 3.3V LVTTL on its outputs while accepting 5V TTL levels on its inputs, making it directly compatible with vintage Sharp MZ and other Z80-based hardware without any additional level shifting.
<div style="padding-top: 0.8em;"></div>
The CPLD design is written in VHDL and built with <b>Altera Quartus II 13.0.1 SP1 (Web Edition)</b>. Because each host machine has slightly different bus timing requirements and memory map constraints, a separate VHDL implementation is maintained for each supported host:
</div>
<div style="padding-top: 0.4em;"></div>
| VHDL Variant | Host Machine | Directory |
|---|---|---|
| `tzpuFusionX.vhd` (MZ80A) | Sharp MZ-80A | `CPLD/v1.0/MZ80A/` |
| `tzpuFusionX.vhd` (MZ700) | Sharp MZ-700 | `CPLD/v1.0/MZ700/` |
| `tzpuFusionX.vhd` (MZ2000) | Sharp MZ-2000 | `CPLD/v1.0/MZ2000/` |
| `tzpuFusionX.vhd` (PCW8256) | Amstrad PCW-8256 | `CPLD/v1.0/PCW8256/` |
<div style="padding-top: 1.2em;"></div>
<a name="cpld-purpose" id="cpld-purpose"></a>
<font style="color: cyan;" size="4">Purpose and Role</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The CPLD performs several functions that would be impractical or impossible to implement directly in software on the SOM:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">Voltage level translation</font><br>— Bridges the 5V TTL Z80 host bus to the 3.3V LVTTL signals used by the SOM. The MAX7000AE is 5V tolerant on inputs and drives outputs at 3.3V, which exceeds the 2.4V switching threshold of 5V TTL receivers, giving up to 25mA drive per pin.</li>
<li><font style="color: orange;" size="3">Cycle-accurate Z80 bus timing</font><br>— The CPLD implements a hardware FSM clocked by a 50MHz external oscillator that samples the host Z80 clock and reproduces the precise T-state sequence for every bus cycle type. This offloads all critical timing from the SOM, which only needs to respond with data within the window defined by the CPLD FSM.</li>
<li><font style="color: orange;" size="3">SOM interface bridging</font><br>— Converts between the Z80 parallel bus protocol and the SPI + 8-bit GPIO interface used by the SOM kernel module, translating bus events into a format that the SSD202 can service efficiently from a Linux kernel thread.</li>
<li><font style="color: orange;" size="3">Video and audio switching</font><br>— Controls multiplexers that select between the host machine's native video/audio output and the SOM video/audio for routing to the monitor and speakers via daughter board connectors. Switching is commanded by the SOM over SPI.</li>
<li><font style="color: orange;" size="3">Video sync and clock generation</font><br>— Generates composite sync (<code>VGA_CSYNCn</code>) from the SOM VSync and HSync signals, detects blanking intervals, generates a 25MHz pixel clock for the monochrome DAC (by dividing the 50MHz oscillator), and produces a colour carrier frequency signal (<code>VGA_COLR</code>) for composite colour output.</li>
<li><font style="color: orange;" size="3">Reset management</font><br>— Monitors the host Z80 RESET line and implements a dual-press reset protocol: a single reset press asserts a soft reset to the SOM (allowing the Z80 application to reinitialise), while a second press within one second drives the SOM <code>PM_RESET</code> line to force a full SOM power-cycle reboot.</li>
<li><font style="color: orange;" size="3">USB power control</font><br>— Controls the USB VBUS power enable signal under SOM command.</li>
</font></ul>
</div>
<div style="padding-top: 1.2em;"></div>
<a name="cpld-fsm" id="cpld-fsm"></a>
<font style="color: cyan;" size="4">Z80 Bus FSM</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The heart of the CPLD design is a finite state machine (<code>SOMFSMState</code>) that tracks and reproduces the Z80 bus cycle state at 50MHz resolution. The FSM monitors the host Z80 clock edges and the bus control signals (MREQ, IORQ, RD, WR, M1, RFSH, BUSRQ, HALT, WAIT) to classify each bus cycle and step through the correct T-state sequence:
</div>
<div style="padding-top: 0.4em;"></div>
| FSM State | Z80 Bus Cycle | Description |
|---|---|---|
| `IdleCycle` | — | Bus is idle; waiting for MREQ or IORQ assertion. |
| `FetchCycle` | Opcode Fetch (M1) | M1 + MREQ + RD active; address and data phases timed across T1T3. |
| `RefreshCycle` | DRAM Refresh | RFSH + MREQ active; lower 7 bits of address presented for DRAM row refresh. |
| `ReadCycle` | Memory Read | MREQ + RD active; address presented T1, data sampled T3. |
| `WriteCycle` | Memory Write | MREQ + WR active; address and data presented T1T2, write strobed T3. |
| `ReadIOCycle` | I/O Read | IORQ + RD active; I/O address and data phases with WAIT support. |
| `WriteIOCycle` | I/O Write | IORQ + WR active; I/O address and data presented with WAIT support. |
| `HaltCycle` | HALT | Z80 HALT assertion detected; repeated NOP fetch cycles suppressed. |
| `BusReqCycle` | Bus Request | BUSRQ asserted; BUSACK driven, bus lines tri-stated, SOM notified. |
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
<div style="padding-top: 0.8em;"></div>
Each state has numbered sub-states (e.g. <code>FetchCycle_11</code>, <code>FetchCycle_20</code>) corresponding to individual half-cycles within the T-state, allowing the CPLD to assert or deassert control signals with sub-clock-cycle precision relative to the host CLK edges.
<div style="padding-top: 0.8em;"></div>
A secondary <code>CTRLFSMState</code> FSM handles SPI command processing (<code>CTRLCMD_Idle</code> → <code>CTRLCMD_ReadIOWrite</code>) independently of the main bus cycle FSM, so that SPI transactions from the SOM do not block Z80 bus cycle servicing.
</div>
<div style="padding-top: 1.2em;"></div>
<a name="cpld-som-interface" id="cpld-som-interface"></a>
<font style="color: cyan;" size="4">SOM Interface</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The CPLD presents two distinct interfaces to the SOM:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">SPI slave (write path)</font><br>— A 4-wire SPI slave (<code>VSOM_SPI_CLK</code>, <code>VSOM_SPI_MOSI</code>, <code>VSOM_SPI_MISO</code>, <code>VSOM_SPI_CSn</code>) receives commands and data from the SOM. Up to 4 bytes per frame are shifted in via a serial shift register and decoded into bus control commands (memory write data, I/O write data, video/audio source selection, USB power control). The SPI clock polarity is parameterised (<code>SPI_CLK_POLARITY</code>) to accommodate different SOM SPI configurations.</li>
<li><font style="color: orange;" size="3">8-bit parallel bus (read path)</font><br>— An 8-bit output bus (<code>VSOM_DATA_OUT[7:0]</code>) with a <code>VSOM_HBYTE</code> select line presents either the low or high byte of the current Z80 address/data word to the SOM GPIO inputs. Additional single-bit status lines report: <code>VSOM_READY</code> (FSM idle), <code>VSOM_LTSTATE</code> (last T-state of current cycle), <code>VSOM_BUSRQ</code>, <code>VSOM_BUSACK</code>, <code>VSOM_INT</code>, <code>VSOM_NMI</code>, <code>VSOM_WAIT</code>, and <code>VSOM_RESET</code>.</li>
</font></ul>
This split architecture — SPI for writes, GPIO parallel bus for reads — matches the relative performance characteristics of the SSD202: SPI is clocked and reliable for multi-byte writes, while GPIO direct register access gives the lowest possible read latency for sampling bus state within a Z80 T-state window.
</div>
<div style="padding-top: 1.2em;"></div>
<a name="cpld-build" id="cpld-build"></a>
<font style="color: cyan;" size="4">Building the CPLD Image</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The CPLD bitstream is produced using <b>Altera Quartus II 13.0.1 SP1 Web Edition</b>, which is available as a free download from the Intel FPGA (formerly Altera) website. The Web Edition supports all MAX7000AE devices and is sufficient for this project.
<div style="padding-top: 0.8em;"></div>
<font style="color: cyan;" size="3">Opening the Project</font><br>
Each host machine variant has its own Quartus project in the corresponding subdirectory. To build the MZ-80A variant, for example:
<pre style="font-size: 0.70em; line-height: 1.3em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;"># Open in Quartus II GUI:
File -> Open Project -> CPLD/v1.0/MZ80A/build/tzpuFusionX_MZ80A.qpf
# Or launch from the command line using the Quartus shell:
quartus_sh --flow compile tzpuFusionX_MZ80A
</pre>
The project references three VHDL source files (paths relative to the project <code>build/</code> directory):
<ul style="line-height: 1.6em;"><font size="3">
<li><code>../tzpuFusionX_Toplevel.vhd</code> — top-level entity instantiation and I/O pin definitions</li>
<li><code>../tzpuFusionX_pkg.vhd</code> — shared package (types, constants)</li>
<li><code>../tzpuFusionX.vhd</code> — main RTL architecture (FSMs, SPI, bus interface, video/audio control)</li>
</font></ul>
<font style="color: cyan;" size="3">Compilation</font><br>
In the Quartus GUI select <b>Processing → Start Compilation</b> (or press Ctrl+L). The tool runs Analysis &amp; Synthesis, Fitter, Assembler and Timing Analysis in sequence. A successful build produces:
<pre style="font-size: 0.70em; line-height: 1.3em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">build/output_files/tzpuFusionX_MZ80A.pof # Programmer Object File (JTAG programming)
build/output_files/tzpuFusionX_MZ80A.fit.rpt # Fitter report (resource usage)
build/output_files/tzpuFusionX_MZ80A.sta.rpt # Timing analysis report
</pre>
The <code>.pof</code> file is the binary image used to program the physical CPLD device.
<div style="padding-top: 0.8em;"></div>
<font style="color: cyan;" size="3">Programming the CPLD</font><br>
Programming is performed via JTAG using an Altera USB-Blaster or compatible JTAG adapter connected to the 10-pin JTAG header on the <i>FusionX</i> board:
<ol style="line-height: 1.6em;"><font size="3">
<li>Connect the USB-Blaster to the <i>FusionX</i> JTAG header and the host PC.</li>
<li>Power the <i>FusionX</i> board (the CPLD must be powered during programming).</li>
<li>In Quartus II, open <b>Tools → Programmer</b>.</li>
<li>Load the chain description file: <code>build/output_files/tzpuFusionX_MZ80A.cdf</code>.</li>
<li>Verify the USB-Blaster is detected in the hardware list, then click <b>Start</b>.</li>
<li>Programming completes in a few seconds; the CPLD becomes active immediately on completion.</li>
</font></ol>
The CPLD retains its programmed logic indefinitely without power (MAX7000AE uses EEPROM-based configuration cells) so the device only needs to be programmed once per build or when updating to a new bitstream.
</div>
--------------------------------------------------------------------------------------------------------
## <font style="color: yellow;" size="6">Software</font>
<font size="2">Under construction.</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The <i>FusionX</i> software stack spans from the Linux operating system through to dedicated kernel modules and user-space utilities. The complete software set is built using a customised SigmaStar build environment and loaded onto the SOM's SPI NAND flash. On boot, U-boot initialises the SOM and hands off to the Linux kernel, which loads the Buildroot root filesystem. The <i>FusionX</i> startup script then configures the system and brings the Z80 emulator online.
<div style="padding-top: 0.8em;"></div>
The software components are:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">Linux OS</font><br>— Kernel 4.9-rt (PREEMPT_RT) with Buildroot root filesystem running on the SigmaStar SSD202 dual-core Cortex-A7.</li>
<li><font style="color: orange;" size="3">z80drv.ko</font><br>— Linux kernel module implementing the Z80 CPU emulator and host hardware interface. Runs the Z80 emulation loop on a dedicated CPU core.</li>
<li><font style="color: orange;" size="3">ttymzdrv.ko</font><br>— Linux TTY kernel module that presents the Sharp MZ keyboard and display as a standard Linux terminal device (<code>/dev/ttymz0</code>).</li>
<li><font style="color: orange;" size="3">z80ctrl</font><br>— User-space command-line utility for controlling the z80drv kernel module: load ROM images, add virtual hardware devices, start/stop emulation and inspect emulated memory.</li>
<li><font style="color: orange;" size="3">k64fcpu</font><br>— User-space daemon emulating a K64F virtual CPU. Used in TZFS mode to manage ROM loading and inter-processor communication with the Z80 emulator.</li>
<li><font style="color: orange;" size="3">sharpbiter</font><br>— Sharp MZ arbiter daemon, coordinating access to the shared Sharp MZ hardware resources between the Z80 emulator and the Linux TTY driver.</li>
</font></ul>
Startup is handled by <code>start_FusionX.sh</code>, which loads <code>ttymzdrv.ko</code>, starts a getty login session on <code>/dev/ttymz0</code>, pins all Linux processes and IRQs to CPU0, loads <code>z80drv.ko</code> onto the isolated CPU1, then launches the <code>k64fcpu</code> and <code>sharpbiter</code> daemons. Two pre-built startup modes are provided:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">RFS mode</font><br>(<code>startZ80_RFS.sh</code>) — loads the ROM Filing System virtual hardware device and starts the MZ-80A emulator with 40- or 80-column ROM images.</li>
<li><font style="color: orange;" size="3">TZFS mode</font><br>(<code>startZ80_TZFS.sh</code>) — loads the tranZPUter SW virtual hardware device and starts the <code>k64fcpu</code> K64F daemon which manages Monitor and TZFS ROM image loading.</li>
</font></ul>
</div>
<a name="architecture" id="architecture"></a>
###### <font style="color: yellow;" size="5">Architecture</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The <i>FusionX</i> software architecture is layered, with each layer handling a distinct responsibility. From the host machine's perspective the flow is entirely transparent — the Z80 socket behaves as a normal Z80 CPU while the SOM is silently intercepting and emulating every bus cycle.
<div style="padding-top: 0.8em;"></div>
<pre style="font-size: 0.70em; line-height: 1.3em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;">
Sharp MZ Host
+------------------------------------------+
| Z80 DIP-40 Socket |
+--------------+---------------------------+
| Z80 bus (address, data, control)
+--------------v---------------------------+
| CPLD (Altera MAX 7000A) |
| . 5V &lt;-&gt; 3.3V level translation |
| . Cycle-accurate Z80 bus timing |
| . 50 MHz internal clock |
+--------------+---------------------------+
| SPI (50 MHz) + 8-bit GPIO bus
+--------------v---------------------------+
| SSD202 SOM -- CPU1 (dedicated) |
| +--------------------------------------+|
| | z80drv.ko kernel module ||
| | +----------------------------------+||
| | | z80io.c (GPIO/SPI HAL) |||
| | +----------------------------------+||
| | | Zeta Z80 CPU emulator core |||
| | +----------------------------------+||
| | | Virtual hardware modules |||
| | | (z80vhw_*.c, inline) |||
| | +----------------------------------+||
| +--------------------------------------+|
| |
| SSD202 SOM -- CPU0 (Linux) |
| +--------------------------------------+|
| | Linux 4.9-rt / Buildroot rootfs ||
| | ttymzdrv.ko --&gt; /dev/ttymz0 ||
| | z80ctrl (control utility) ||
| | k64fcpu (K64F daemon) ||
| | sharpbiter (MZ arbiter) ||
| +--------------------------------------+|
+------------------------------------------+
</pre>
</div>
<div style="padding-top: 1.2em;"></div>
<a name="dual-core-design" id="dual-core-design"></a>
<font style="color: cyan;" size="4">Dual-Core Design</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The SSD202's two Cortex-A7 cores operate under a strict separation of responsibility. At startup every Linux process and every hardware IRQ affinity is migrated to CPU0, leaving CPU1 exclusively available to the Z80 emulation kernel thread. The CPU frequency governor is set to performance mode (1.2GHz fixed) after the emulator starts to prevent frequency-scaling transitions from introducing timing variation in the emulation loop.
<div style="padding-top: 0.8em;"></div>
<b>CPU0 — Linux and User-Space Services</b><br>
Runs the complete Linux 4.9-rt operating system, all user-space daemons and handles all hardware interrupts. Key responsibilities on CPU0 include:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">ttymzdrv.ko</font><br>— Linux TTY kernel module that maps the Sharp MZ keyboard and display to <code>/dev/ttymz0</code>. Supports suspend and resume, enabling the user to switch seamlessly between a Z80 session and a Linux console at the host machine without losing state in either.</li>
<li><font style="color: orange;" size="3">z80ctrl utility</font><br>— Command-line tool for runtime control of the Z80 emulator: loading ROM images, registering virtual hardware devices, starting and stopping the emulation loop, and inspecting emulated memory. Communicates with <code>z80drv.ko</code> via a kernel character device.</li>
<li><font style="color: orange;" size="3">k64fcpu daemon</font><br>— User-space daemon that emulates a K64F virtual CPU. Active in TZFS mode; it manages Monitor and TZFS ROM image loading into the emulator's memory space and relays inter-processor commands to <code>z80drv.ko</code>.</li>
<li><font style="color: orange;" size="3">sharpbiter daemon</font><br>— Sharp MZ arbiter; coordinates access to the shared Sharp MZ keyboard and display hardware between the TTY driver and the Z80 emulator so that both can operate without conflicting on the underlying I/O registers.</li>
<li><font style="color: orange;" size="3">WiFi and web server</font><br>— The SOM's integrated 802.11 b/g/n transceiver (SSW101B) provides network connectivity. A lightweight web server on CPU0 can serve configuration and status pages, and the WiFi stack handles OTA firmware delivery via SD card auto-upgrade on boot.</li>
</font></ul>
<b>CPU1 — Z80 Emulator (dedicated)</b><br>
Exclusively runs the <code>kthread_z80</code> kernel thread spawned by <code>z80drv.ko</code>. No other process or interrupt is ever scheduled on CPU1 after initialisation. The emulation loop on CPU1:
<ul style="line-height: 1.6em;"><font size="3">
<li>Calls the Zeta Z80 CPU core for each instruction execution step</li>
<li>Dispatches each resulting memory or I/O access to the correct handler — physical host hardware, kernel-resident RAM image, or a virtual hardware module function</li>
<li>Drives the GPIO and SPI hardware via <code>z80io.c</code> to assert or sample the Z80 bus signals through the CPLD</li>
<li>Runs at 1.2GHz with the PREEMPT_RT kernel ensuring minimal interrupt jitter even from CPU0 activity</li>
</font></ul>
</div>
<div style="padding-top: 1.2em;"></div>
<a name="cpld-bus-interface" id="cpld-bus-interface"></a>
<font style="color: cyan;" size="4">CPLD Bus Interface</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The hardware path from the SOM to the Z80 host socket passes through an Altera MAX 7000A CPLD. This device serves two essential roles:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">Voltage level translation</font><br>— The CPLD is 5V tolerant on its inputs and drives outputs at 3.3V Low Voltage TTL levels. Since the 5V TTL switching threshold is approximately 2.4V the CPLD can drive 5V host logic directly with up to 25mA per pin, making the board compatible with unmodified vintage Z80 hardware.</li>
<li><font style="color: orange;" size="3">Cycle-accurate Z80 bus timing</font><br>— The CPLD embeds state machines clocked by an external 50MHz oscillator. These state machines sample the Z80 host clock and reproduce the precise T-state sequence for each bus cycle (fetch, memory read/write, I/O read/write) as defined in the Z80 state diagrams. This means the SOM kernel module does not need to replicate sub-microsecond Z80 timing in software — the CPLD handles it in hardware.</li>
</font></ul>
The SOM communicates with the CPLD through two parallel channels:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">SPI channel (50MHz)</font><br>— used for writing data and commands to the CPLD. SPI write is used in preference to GPIO for host bus writes because it is clocked and therefore more reliable for multi-byte transfers at speed.</li>
<li><font style="color: orange;" size="3">8-bit GPIO bus</font><br>— used by <code>z80io.c</code> for reading bus status and address/data values from the CPLD. Direct register access is used (bypassing the SigmaStar HAL API after initialisation) to minimise read latency. The maximum read throughput achievable via the SSD202 GPIO structure is approximately 2MB/s for an 8-bit byte — fast enough to service Z80 bus cycles at typical host clock rates (1MHz6MHz) when combined with the CPLD buffering.</li>
</font></ul>
Because the GPIO read throughput sets an upper bound on bus transaction rate, Z80 programs execute from kernel-resident memory images rather than being read from the physical host memory bus on every access. ROM images are loaded into kernel memory at startup, and all memory accesses by the emulated Z80 are serviced from there — the physical host bus is only engaged when a <code>PHYSICAL</code>-type block is encountered (e.g. for host video RAM or hardware registers that must be accessed on the real hardware).
</div>
<div style="padding-top: 1.2em;"></div>
<a name="memory-architecture" id="memory-architecture"></a>
<font style="color: cyan;" size="4">Memory Architecture</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The 128MB DRAM on the SSD202 SOM is shared between the Linux operating system and the Z80 kernel module. The kernel module allocates a contiguous region of physically-addressed kernel memory to hold ROM and RAM images for the emulated Z80. This region is accessed directly by the <code>kthread_z80</code> running on CPU1, with no virtual memory translation overhead in the inner emulation loop.
<div style="padding-top: 0.8em;"></div>
The emulated Z80 sees a configurable memory map across the standard 64KB (0x00000xFFFF) address space. Each region is assigned one of the following access types:
</div>
<div style="padding-top: 0.4em;"></div>
| Type | Description |
|------|-------------|
| `kernel RAM` | Read/write region backed by a kernel-allocated DRAM buffer. Standard RAM for the emulated machine. |
| `kernel ROM` | Read-only region in kernel DRAM. Write cycles are silently discarded. Used for Monitor ROMs, BASIC ROMs, User ROMs, TZFS ROM pages. |
| `PHYSICAL` | Pass-through to real host hardware — the SOM releases the CPLD bus and the host hardware responds to the cycle directly. Used for host video RAM and I/O registers that must interact with real hardware. |
| `VIRTUAL` | Each access triggers a C handler function within the kernel module. Used to emulate peripheral devices (floppy controller, QuickDisk, RFS banking logic) without any real hardware. |
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
<div style="padding-top: 0.8em;"></div>
ROM images are loaded into kernel memory at startup by <code>z80ctrl --loadrom</code> (or automatically by the active virtual hardware module or the <code>k64fcpu</code> daemon in TZFS mode). Multiple ROM page sets can be resident simultaneously — the RFS virtual hardware module, for example, maintains up to four switchable ROM pages (MROM, User ROM I/II/III) for 40-column and 80-column configurations.
<div style="padding-top: 0.8em;"></div>
Machine timing constants for each supported host (MZ-80A, MZ-700, MZ-2000, PCW-8256) are defined in <code>z80driver.h</code> and used by the emulation loop to pace bus cycles at the correct rate relative to the host clock, ensuring that time-sensitive software (tape motor control, serial I/O, delay loops) behaves as it would on original hardware.
</div>
<div style="padding-top: 1.2em;"></div>
<a name="virtual-hardware-modules" id="virtual-hardware-modules"></a>
<font style="color: cyan;" size="4">Virtual Hardware Modules</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
Virtual hardware modules are C source files (<code>z80vhw_*.c</code>) that define the behaviour of a specific host machine or peripheral set. Rather than being compiled as separately-linked objects they are <code>#include</code>d directly into <code>z80driver.c</code>, so their handler functions are inlined into the emulation dispatch path with no function-call overhead.
<div style="padding-top: 0.8em;"></div>
Up to five virtual hardware devices can be active simultaneously (<code>MAX_VIRTUAL_DEVICES 5</code>). Devices are registered at runtime before the emulator starts using <code>z80ctrl --adddev --device &lt;name&gt;</code>. Each registered device receives memory read, memory write, I/O read and I/O write callbacks for the address ranges it claims, and can optionally install its own ROM images and configure the memory map during initialisation.
<div style="padding-top: 0.8em;"></div>
The available modules and the host machines they support are:
</div>
<div style="padding-top: 0.4em;"></div>
| Module | Host | Role |
|--------|------|------|
| `z80vhw_mz80a.c` | Sharp MZ-80A | Original MZ-80A memory map, keyboard matrix and display I/O — no extensions. |
| `z80vhw_mz700.c` | Sharp MZ-700 | MZ-700 bank-switching, video and keyboard I/O emulation. |
| `z80vhw_mz2000.c` | Sharp MZ-2000 | MZ-2000 memory map, extended video modes and I/O. |
| `z80vhw_pcw.c` | Amstrad PCW-8256 | PCW-8256 memory/bank paging and peripheral I/O. |
| `z80vhw_rfs.c` | MZ-80A + RFS board | ROM Filing System: manages four switchable ROM pages (40-col and 80-col sets), SD-based MZF program loading, bank switching. |
| `z80vhw_tzpu.c` | MZ-80A + tranZPUter SW | tranZPUter SW virtual hardware; the kernel-side driver works with the userspace <code>k64fcpu</code> daemon to provide K64F virtual CPU behaviour, TZFS ROM page management and CP/M support. |
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
<div style="padding-top: 0.8em;"></div>
The TZPU module (<code>z80vhw_tzpu.c</code>) is architecturally distinct from the others. Because the K64F co-processor behaviour is complex and stateful, it is split across two components: the <code>z80vhw_tzpu.c</code> kernel-side stub handles fast bus-cycle dispatch while the <code>k64fcpu</code> user-space daemon on CPU0 manages ROM loading, memory bank selection and higher-level K64F command processing. The two halves communicate via a shared memory region in the kernel module.
</div>
<a name="build" id="build"></a>
###### <font style="color: yellow;" size="5">Build</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The complete <i>FusionX</i> OS and application set is built using the <code>Build_FusionX.sh</code> script, which wraps the SigmaStar SDK build system and produces a ready-to-flash NAND image. Building requires a Linux host with the ARM cross-compiler toolchain installed.
<div style="padding-top: 0.8em;"></div>
<font style="color: cyan;" size="4">Prerequisites</font>
<ul style="line-height: 1.6em;"><font size="3">
<li>ARM cross-compiler: <code>arm-linux-gnueabihf-gcc</code> (e.g. from <code>gcc-arm-linux-gnueabihf</code> package)</li>
<li>SigmaStar SDK source tree (kernel, U-boot, Buildroot) in the parent directory structure expected by <code>Build_FusionX.sh</code></li>
<li>FusionX application source in the <code>../FusionX</code> directory relative to the linux build directory</li>
<li>Standard build tools: <code>make</code>, <code>cmake</code>, <code>bc</code>, <code>libssl-dev</code></li>
</font></ul>
<font style="color: cyan;" size="4">Building the Full OS Image</font>
The build is launched from the <code>software/linux/</code> directory:
<pre style="font-size: 0.70em; line-height: 1.3em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;"># Build full image for FusionX (project 2D06, SPI NAND, SSD202, 256MB flash)
./Build_FusionX.sh -f nand -p ssd202 -o 2D06 -m 256
</pre>
This builds in sequence: U-boot bootloader, Linux kernel (using the FusionX custom defconfig <code>infinity2m_spinand_fusionx_defconfig</code>), Buildroot root filesystem and the FusionX application set. Output images are written to <code>project/image/output/images/</code>.
For the standard SigmaStar reference configuration use project <code>2D07</code> instead.
<div style="padding-top: 0.8em;"></div>
<font style="color: cyan;" size="4">Building Kernel Modules Only</font>
The kernel modules can be rebuilt independently against an already-built kernel tree, which is useful during development:
<pre style="font-size: 0.70em; line-height: 1.3em; background: #1a1a1a; padding: 1em; border-radius: 4px; overflow-x: auto;"># Build z80drv kernel module
cd software/FusionX/src/z80drv/src.mz80a
make
# Build ttymzdrv kernel module
cd software/FusionX/src/ttymz
make
</pre>
The resulting <code>z80drv.ko</code> and <code>ttymzdrv.ko</code> files can be copied directly to the <code>/apps/FusionX/modules/</code> directory on the running SOM (via SSH or SD card) and loaded with <code>insmod</code>.
<div style="padding-top: 0.8em;"></div>
<font style="color: cyan;" size="4">Flashing and Updates</font>
The flash image produced by the build script is programmed to the SOM SPI NAND via the SigmaStar ISP tool over USB. Once the initial image is installed, subsequent updates can be delivered via SD card — when the SOM boots with a suitably prepared SD card present it will auto-upgrade the NAND image without requiring a USB connection.
</div>
###### <font style="color: yellow;" size="5">Linux</font>
<font size="2">Under construction.</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The Linux platform runs on the SigmaStar SSD202 (Infinity2M) SOM — a 29mm × 29mm stamp module containing a dual-core ARM Cortex-A7 at 1.2GHz, 128MB DRAM, 256MB SPI NAND flash and an integrated 802.11 b/g/n WiFi transceiver. The kernel is Linux 4.9 with the PREEMPT_RT real-time patch applied to minimise scheduling latency, which is essential for responsive Z80 emulation.
<div style="padding-top: 0.8em;"></div>
The complete OS image — U-boot bootloader, Linux kernel, Buildroot root filesystem and FusionX application set — is assembled using the <code>Build_FusionX.sh</code> script, a customised version of the SigmaStar SDK build system. Two project targets are defined:
<ul style="line-height: 1.6em;"><font size="3">
<li><font style="color: orange;" size="3">2D06</font><br>— FusionX custom configuration using the <code>infinity2m_spinand_fusionx_defconfig</code> kernel defconfig.</li>
<li><font style="color: orange;" size="3">2D07</font><br>— Standard SigmaStar reference configuration using <code>infinity2m_spinand_ssc011a_s01a_minigui_defconfig</code>.</li>
</font></ul>
The build script is invoked as: <code>Build_FusionX.sh -f nand -p ssd202 -o 2D06 -m 256</code> and produces a full flash image ready for programming to the SOM NAND.
<div style="padding-top: 0.8em;"></div>
A key aspect of the Linux configuration is CPU isolation. At startup all Linux processes and hardware IRQs are migrated to CPU0. CPU1 is then dedicated exclusively to the <code>kthread_z80</code> kernel thread which runs the Z80 emulation loop. This CPU affinity separation, combined with the PREEMPT_RT kernel, gives the Z80 emulator the most consistent and lowest-latency access to the host hardware interface. The CPU performance governor is also set to maximum frequency (1.2GHz) after the Z80 emulator is running to avoid frequency scaling causing timing variation in the emulation loop.
<div style="padding-top: 0.8em;"></div>
The root filesystem is a Buildroot-based minimal Linux environment stored in the SOM NAND flash. An optional SD card can extend storage for Sharp MZ application software, ROM images and additional Linux utilities. When a suitably prepared SD card is present at boot the SOM will auto-upgrade from it, simplifying firmware updates.
</div>
###### <font style="color: yellow;" size="5">Z80 Emulator</font>
<font size="2">Under construction.</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The Z80 emulator is implemented as a Linux kernel module, <code>z80drv.ko</code> (v1.4, April 2023). It uses the <a href="https://github.com/redcode/Z80">Zeta Z80 CPU emulator library</a> by Manuel Sainz de Baranda y Goñi as its Z80 instruction-set core, wrapped in a kernel-space driver that interfaces with the SSD202 GPIO hardware and the CPLD Z80 host interface.
<div style="padding-top: 0.8em;"></div>
The hardware path from the SOM to the Z80 host socket runs: SSD202 GPIO / SPI → CPLD → Z80 DIP-40 socket. The CPLD handles accurate Z80 bus timing using a 50MHz clock, so the kernel module does not need to reproduce precise T-state timing itself. The GPIO interface is managed by <code>z80io.c</code>, which calls the SigmaStar HAL for initialisation but accesses registers directly for bit-level read/write operations to minimise latency. The practical read throughput of the SSD202 GPIO structure is approximately 2MB/s for an 8-bit byte, which means programs execute from emulated (kernel) memory rather than from the physical host memory over the bus.
<div style="padding-top: 0.8em;"></div>
The emulator supports the following host machines, each with its own virtual hardware module:
<table style="font-size: 0.85em; width: 100%; border-collapse: collapse; margin-top: 0.5em;">
<thead>
<tr style="background: #2a2a2a;">
<th style="padding: 0.4em 0.8em; text-align: left; border: 1px solid #444;">Virtual Hardware Module</th>
<th style="padding: 0.4em 0.8em; text-align: left; border: 1px solid #444;">Host Machine</th>
<th style="padding: 0.4em 0.8em; text-align: left; border: 1px solid #444;">Description</th>
</tr>
</thead>
<tbody>
<tr><td style="padding: 0.4em 0.8em; border: 1px solid #444;"><code>z80vhw_mz80a.c</code></td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">Sharp MZ-80A</td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">Original MZ-80A behaviour, no additions</td></tr>
<tr><td style="padding: 0.4em 0.8em; border: 1px solid #444;"><code>z80vhw_mz700.c</code></td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">Sharp MZ-700</td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">Original MZ-700 behaviour, no additions</td></tr>
<tr><td style="padding: 0.4em 0.8em; border: 1px solid #444;"><code>z80vhw_mz2000.c</code></td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">Sharp MZ-2000</td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">MZ-2000 emulation</td></tr>
<tr><td style="padding: 0.4em 0.8em; border: 1px solid #444;"><code>z80vhw_pcw.c</code></td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">Amstrad PCW-8256</td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">PCW-8256 emulation</td></tr>
<tr><td style="padding: 0.4em 0.8em; border: 1px solid #444;"><code>z80vhw_rfs.c</code></td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">MZ-80A + RFS</td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">ROM Filing System virtual hardware for MZ-80A</td></tr>
<tr><td style="padding: 0.4em 0.8em; border: 1px solid #444;"><code>z80vhw_tzpu.c</code></td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">MZ-80A + tranZPUter SW</td><td style="padding: 0.4em 0.8em; border: 1px solid #444;">tranZPUter SW virtual hardware; combines kernel driver with userspace <code>k64fcpu</code> daemon</td></tr>
</tbody>
</table>
<div style="padding-top: 0.8em;"></div>
The virtual hardware modules are compiled inline into <code>z80drv.ko</code> rather than linked as separate objects, which eliminates function call overhead in the emulation hot path. Up to five virtual hardware devices can be active simultaneously (<code>MAX_VIRTUAL_DEVICES 5</code>). Devices are added at runtime using <code>z80ctrl --adddev --device &lt;name&gt;</code> before starting the emulator.
<div style="padding-top: 0.8em;"></div>
The <code>z80ctrl</code> utility provides full runtime control of the emulator from the Linux command line:
<ul style="line-height: 1.6em;"><font size="3">
<li><code>--adddev --device &lt;name&gt;</code> — add a virtual hardware device (rfs, tzpu, mz700, mz80a, mz2000, pcw)</li>
<li><code>--start</code> / <code>--stop</code> — start or stop the Z80 emulation loop</li>
<li><code>--loadrom --file &lt;path&gt; --addr &lt;hex&gt; --type &lt;n&gt;</code> — load a ROM binary into emulated memory</li>
<li><code>--mem --addr &lt;hex&gt; --len &lt;n&gt;</code> — inspect emulated memory contents</li>
<li><code>--cmd &lt;hex&gt;</code> — send a command byte directly to the CPLD/Z80 gateway</li>
</font></ul>
<div style="padding-top: 0.8em;"></div>
The <code>ttymzdrv.ko</code> module (<code>ttymz.c</code>, v1.2, July 2023) provides a standard Linux TTY interface on <code>/dev/ttymz0</code> backed by the Sharp MZ keyboard and display hardware. This allows the host machine's console to be used as a Linux terminal — running a getty login session — while also supporting suspend and resume to switch the display between Linux and the Z80 emulation session without losing state. Supported hosts are MZ-80A, MZ-700 and MZ-2000.
</div>
--------------------------------------------------------------------------------------------------------
## <font style="color: yellow;" size="6">Daughter Boards</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The tranZPUter series was initially developed in the Sharp MZ-80A and was primarily a Z80 replacement. As the concept evolved and the tranZPUter SW-700 was developed for the MZ-700 it became more of an integral component of the machine, offering original and upgraded Video and Audio capabilites by intercepting and routing existing signals.
The tranZPUter series was initially developed in the Sharp MZ-80A and was primarily a Z80 replacement. As the concept evolved and the tranZPUter SW-700 was developed for the MZ-700 it became more of an integral component of the machine, offering original and upgraded Video and Audio capabilities by intercepting and routing existing signals.
<div style="padding-top: 0.8em;"></div>
After significant developments on the tranZPUter SW-700 it became desirable to port it back to the MZ-80A and MZ-2000 but these machines had different CPU orientation and signal requirements, ie. driving an internal and external monitor. This requirement led to the concept of daughter boards, where a specific board would be designed and developed for
@@ -207,7 +633,7 @@ the target host and would plug into the tranZPUter SW-700 card. Ideally I wanted
<div style="padding-top: 0.8em;"></div>
During the design of the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> one of the main requirements was to make the board small, the Z80 orientation changeable and also compatible with the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup> so that it could fit many machines and be interchangeable. As the SW-700 also interfaced to the Video and Audio of the machines
and each was quite different, it became apparent that the tran<i>ZPU</i>ter<sup>FusionX</sup> needed to include a concept to allow different video/audio interfaces according to the targetted host. This concept was realised via daughter boards. Two connectors would link the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> to a daughter board which would be
and each was quite different, it became apparent that the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> needed to include a concept to allow different video/audio interfaces according to the targeted host. This concept was realised via daughter boards. Two connectors would link the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> to a daughter board which would be
specifically designed for the intended host.
<div style="padding-top: 0.8em;"></div>
@@ -226,7 +652,7 @@ The purpose of the MZ-700 daughter board is to interface the video/audio circuit
is switched between the MZ-700 and <i>FusionX</i> under control of the <i>FusionX</i>.
<div style="padding-top: 0.8em;"></div>
The original sound circuity of the MZ-700 drives a speaker directly and in order to inject <i>FusionX</i> audio into the MZ-700 speaker, the mainboard speaker output is routed to the daughter board, level converted and switched under control of the <i>FusionX</I>. The <i>FusionX</i> offers stereo sound so this is selectively switched/mixed with the
The original sound circuitry of the MZ-700 drives a speaker directly and in order to inject <i>FusionX</i> audio into the MZ-700 speaker, the mainboard speaker output is routed to the daughter board, level converted and switched under control of the <i>FusionX</I>. The <i>FusionX</i> offers stereo sound so this is selectively switched/mixed with the
original MZ-700 sound and fed to a Class D amplifier which then drives the internal speaker. Line level stereo output is achieved via an additional 4pin connector and used as required.
<div style="padding-top: 0.8em;"></div>
@@ -241,7 +667,7 @@ This setup allows for Linux or emulated machines, whilst running as an applicati
The MZ-700 daughter board consists of three 4way SPDT analogue switches to route video and audio signals under <i>FusionX</i> control and a Class D power amplifier.
</div>
![MZ700 VideoInterface Schematic6](http://eaw.app/images/VideoInterface_MZ700_V1_0_Schematics-1.png)
![MZ700 VideoInterface Schematic6](../images/VideoInterface_MZ700_V1_0_Schematics-1.png)
<font style="color: cyan;" size="4">MZ-700 Video Interface PCB</font>
@@ -251,16 +677,16 @@ The MZ-700 daughter board PCB is small and compact due to the space restrictions
<div style='content: ""; clear: both; display: table;'>
<div style='width: 35%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/VideoInterface_MZ700_v1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/VideoInterface_MZ700_v1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
<div style='width: 39%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/VideoInterface_MZ700_v1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/VideoInterface_MZ700_v1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
</div>
<div style='content: ""; clear: both; display: table;'>
<div style='width: 80%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/FusionX_MZ700.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/FusionX_MZ700.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
</div>
@@ -284,7 +710,7 @@ The video signals from the mainboard are switched with the <i>FusionX</i> video
The <i>FusionX</i> RGB output is routed to the MZ-2000 external RGB video socket allowing for upto full HD external colour video display.
<div style="padding-top: 0.8em;"></div>
The sound circuity of the MZ-2000 is sent to an audio amplifier on the CRT monitor. This signal is intercepted and switched with the <i>FusionX</i> audio which then drives the CRT monitor amplifier. Line level stereo output is achieved via an additional 4pin connector and used as required.
The sound circuitry of the MZ-2000 is sent to an audio amplifier on the CRT monitor. This signal is intercepted and switched with the <i>FusionX</i> audio which then drives the CRT monitor amplifier. Line level stereo output is achieved via an additional 4pin connector and used as required.
<div style="padding-top: 0.8em;"></div>
</div>
@@ -295,26 +721,26 @@ The sound circuity of the MZ-2000 is sent to an audio amplifier on the CRT monit
The MZ-2000 daughter board consists of two 4way SPDT analogue switches to route video and audio signals under <i>FusionX</i> control. One SPDT switch is used for creating pure black in the modified video signal generated on the <i>FusionX</i> board.
</div>
![MZ2000 VideoInterface Schematic6](http://eaw.app/images/VideoInterface_MZ2000_V1_0_Schematics-1.png)
![MZ2000 VideoInterface Schematic6](../images/VideoInterface_MZ2000_V1_0_Schematics-1.png)
<font style="color: cyan;" size="4">MZ-2000 Video Interface PCB</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The MZ-2000 daughter board PCB is small and compact due to the space restrictions and the number of connectors it must carry. It plugs into the mainboard monitor/IPL male connectors and then presents new CRT monitor, external Video and IPL/RESET switch connectors for all the exising internal cabling.
The MZ-2000 daughter board PCB is small and compact due to the space restrictions and the number of connectors it must carry. It plugs into the mainboard monitor/IPL male connectors and then presents new CRT monitor, external Video and IPL/RESET switch connectors for all the existing internal cabling.
</div>
<div style='content: ""; clear: both; display: table;'>
<div style='width: 50%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/VideoInterface_MZ2000_v1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/VideoInterface_MZ2000_v1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
<div style='width: 50%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/VideoInterface_MZ2000_v1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/VideoInterface_MZ2000_v1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
</div>
<div style='content: ""; clear: both; display: table;'>
<div style='width: 60%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/FusionX_MZ2000.png' height='80%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/FusionX_MZ2000.png' height='80%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
</div>
@@ -323,7 +749,7 @@ The MZ-2000 daughter board PCB is small and compact due to the space restriction
###### <font style="color: yellow;" size="5">MZ-80A Daughter Board</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The purpose of the MZ-80A daughter board is to interface the video/audio/reset circuits of the <i>FusionX</I> board with those of the MZ-80A. The MZ-80A has an internal monochrome CRT, cutouts for and external RGB video socket and internal Audio with an amplifier on the monochrome CRT control board.
The purpose of the MZ-80A daughter board is to interface the video/audio/reset circuits of the <i>FusionX</I> board with those of the MZ-80A. The MZ-80A has an internal monochrome CRT, cutouts for an external RGB video socket and internal Audio with an amplifier on the monochrome CRT control board.
<div style="padding-top: 0.8em;"></div>
The daughter board is designed to plug into the vertical mainboard CRT video connector with a gap so that the data cassette connector can be simultaneously connected. The gap is necessary as the CRT video connector sits close to the rear sidewall so the daughter board must extend forwards towards the keyboard.
@@ -332,7 +758,7 @@ The daughter board is designed to plug into the vertical mainboard CRT video con
It presents all the required connectors to connect the RESET switch (both in and out), internal monitor and external monitor on the same board.
<div style="padding-top: 0.8em;"></div>
The RESET input is intercepted on the daughter board and sent to the <i>FusionX</i>. Technically it isnt needed as the <i>FusionX</i> samples the Z80 Reset which is based on this input, but it can be useful, for example, detecting requests to reboot the SOM (double press) rather than the MZ-80A circuitry.
The RESET input is intercepted on the daughter board and sent to the <i>FusionX</i>. Technically it isn't needed as the <i>FusionX</i> samples the Z80 Reset which is based on this input, but it can be useful, for example, detecting requests to reboot the SOM (double press) rather than the MZ-80A circuitry.
<div style="padding-top: 0.8em;"></div>
The video signals from the mainboard are switched with the <i>FusionX</i> video monochrome signals and sent to the internal CRT monitor. This allows for original video output on the CRT monitor or advanced <i>FusionX</i> text and graphics, resolution subject to the timing constraints of the monitor.
@@ -341,7 +767,7 @@ The video signals from the mainboard are switched with the <i>FusionX</i> video
The <i>FusionX</i> RGB output is routed to the MZ-80A external RGB video socket (if installed) allowing for upto full HD external colour video display.
<div style="padding-top: 0.8em;"></div>
The sound circuity of the MZ-80A is sent to an audio amplifier on the CRT monitor. This signal is intercepted and switched with the <i>FusionX</i> audio which then drives the CRT monitor amplifier. Line level stereo output is achieved via an additional 4pin connector and used as required.
The sound circuitry of the MZ-80A is sent to an audio amplifier on the CRT monitor. This signal is intercepted and switched with the <i>FusionX</i> audio which then drives the CRT monitor amplifier. Line level stereo output is achieved via an additional 4pin connector and used as required.
<div style="padding-top: 0.8em;"></div>
</div>
@@ -352,20 +778,20 @@ The sound circuity of the MZ-80A is sent to an audio amplifier on the CRT monito
The MZ-80A daughter board consists of two 4way SPDT analogue switches to route video and audio signals under <i>FusionX</i> control. One SPDT switch is used for creating pure black in the modified video signal generated on the <i>FusionX</i> board.
</div>
![MZ80A VideoInterface Schematic6](http://eaw.app/images/VideoInterface_MZ80A_V1_0_Schematics-1.png)
![MZ80A VideoInterface Schematic6](../images/VideoInterface_MZ80A_V1_0_Schematics-1.png)
<font style="color: cyan;" size="4">MZ-80A Video Interface PCB</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The MZ-80A daughter board PCB is small and compact with a large punchout to enable connection with the mainboard CRT connector and thru connection of the data cassette signal connector. It plugs into the mainboard CRT monitor connector and then presents new CRT monitor, external Video and RESET In/Out switch connectors to be used with all the exising internal cabling.
The MZ-80A daughter board PCB is small and compact with a large punchout to enable connection with the mainboard CRT connector and thru connection of the data cassette signal connector. It plugs into the mainboard CRT monitor connector and then presents new CRT monitor, external Video and RESET In/Out switch connectors to be used with all the existing internal cabling.
</div>
<div style='content: ""; clear: both; display: table;'>
<div style='width: 47%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/VideoInterface_MZ80A_V1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/VideoInterface_MZ80A_V1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
<div style='width: 50%; padding: 5px; padding-left: 1em; float: left'>
<img src='http://eaw.app/images/VideoInterface_MZ80A_V1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
<img src='../images/VideoInterface_MZ80A_V1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
</div>
</div>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
@@ -384,6 +810,17 @@ The table below contains all the sites referenced in the design and programming
<div style="padding-top: 0.8em;"></div>
<div style="padding-left: 10%;">
<font size="4">
<style>
table {
border-collapse: collapse;
}
tr td {
padding-top: 0em;
}
tr:nth-child(4) td {
padding-top: 0;
}
</style>
<table>
<thead>
<tr>
@@ -438,6 +875,17 @@ The table below contains all the datasheets and manuals referenced in the design
<div style="padding-top: 0.8em;"></div>
<div style="padding-left: 10%;">
<font size="4">
<style>
table {
border-collapse: collapse;
}
tr td {
padding-top: 0em;
}
tr:nth-child(4) td {
padding-top: 0;
}
</style>
<table>
<thead>
<tr>
@@ -548,19 +996,43 @@ The table below contains all the datasheets and manuals referenced in the design
--------------------------------------------------------------------------------------------------------
## <font style="color: yellow;" size="5">Demonstration Videos</font>
<a name="project-preview" id="project-preview"></a>
## <font style="color: yellow;" size="6">Project Preview</font>
<a href="https://t.co/ZP4T3oisrg">MZ-2000 Demo</a>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
Development progress on the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> was shared on X (formerly Twitter) as each milestone was reached. The posts below document key stages from the first hardware bring-up through to running RFS, MZ-700 and MZ-2000 emulation:
<div style="padding-top: 0.8em;"></div>
<a href="https://t.co/6lJoGkNuiP">MZ-700 Demo</a>
<a href="https://x.com/engineerswork1/status/1579209688495054849" target="_blank">https://x.com/engineerswork1/status/1579209688495054849</a><br>
<a href="https://x.com/engineerswork1/status/1583918702415577089" target="_blank">https://x.com/engineerswork1/status/1583918702415577089</a><br>
<a href="https://x.com/engineerswork1/status/1596925535787286528" target="_blank">https://x.com/engineerswork1/status/1596925535787286528</a><br>
<a href="https://x.com/engineerswork1/status/1616571495957909510" target="_blank">https://x.com/engineerswork1/status/1616571495957909510</a><br>
<a href="https://x.com/engineerswork1/status/1630985022604804109" target="_blank">https://x.com/engineerswork1/status/1630985022604804109</a>
</div>
<div style="padding-top: 1.2em;"></div>
<a name="demonstration-videos" id="demonstration-videos"></a>
<font style="color: yellow;" size="5">Demonstration Videos</font>
<div style="padding-top: 0.8em;"></div>
<font style="color: cyan;" size="4">MZ-80A Demo (includes virtual RFS Board)</font>
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr"> <a href="https://t.co/3gbEHVzS6X">pic.twitter.com/3gbEHVzS6X</a></p>&mdash; engineers@work (@engineerswork1) <a href="https://twitter.com/engineerswork1/status/1625281950897303553?ref_src=twsrc%5Etfw">February 13, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<font style="color: cyan;" size="4">MZ-2000 Demo</font>
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="zxx" dir="ltr"><a href="https://t.co/ZP4T3oisrg">pic.twitter.com/ZP4T3oisrg</a></p>&mdash; engineers@work (@engineerswork1) <a href="https://twitter.com/engineerswork1/status/1596925985592864768?ref_src=twsrc%5Etfw">November 27, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<font style="color: cyan;" size="4">MZ-700 Demo</font>
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark"><p lang="en" dir="ltr"> <a href="https://t.co/6lJoGkNuiP">pic.twitter.com/6lJoGkNuiP</a></p>&mdash; engineers@work (@engineerswork1) <a href="https://twitter.com/engineerswork1/status/1586864092601630721?ref_src=twsrc%5Etfw">October 30, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
--------------------------------------------------------------------------------------------------------
## <font style="color: yellow;" size="5">Credits</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
The Z80 Emulation used in the <i>FusionX</i> is (c) 1999-2022 Manuel Sainz de Baranda y Goñi, which is licensed under the LGPL v3 license, source can be found in <a href="https://github.com/redcode/Z80">github</a>.
The Z80 Emulation used in the <i>FusionX</i> is (c) 1999-2022 Manuel Sainz de Baranda y Goñi, which is licensed under the LGPL v3 license, source can be found in <a href="https://github.com/redcode/Z80">Gitea</a>.
<div style="padding-top: 0.8em;"></div>
The SSD202/SOM2D0X build system is based on Linux with extensions by SigmaStar and Industio, licensing can be found in their updated source files.
@@ -571,7 +1043,7 @@ The SSD202/SOM2D0X build system is based on Linux with extensions by SigmaStar a
## <font style="color: yellow;" size="5">Licenses</font>
<div style="text-align: justify; line-height: 1.4em; font-size: 0.8em; font-family:sans-serif;">
This design, hardware and software (attributable components excluding seperately licensed software) is licensed under the GNU Public Licence v3 and free to use, adapt and modify by individuals, groups and educational institutes.
This design, hardware and software (attributable components excluding separately licensed software) is licensed under the GNU Public Licence v3 and free to use, adapt and modify by individuals, groups and educational institutes.
<div style="padding-top: 0.8em;"></div>
No commercial use to be made of this design or any hardware/firmware component without express permission from the author.

1
VERSION vendored Normal file
View File

@@ -0,0 +1 @@
1.00

438
build.sh Executable file
View File

@@ -0,0 +1,438 @@
#!/bin/bash
#########################################################################################################
##
## Name: build.sh
## Created: March 2026
## Author(s): Philip Smart
## Description: FusionX global build script
## Builds all software components for the FusionX tranZPUter board:
## - Z80 assembly ROMs (monitor, MS BASIC, CP/M, TZFS)
## - Linux kernel modules (z80drv, ttymzdrv) for each target machine
## - User-space applications (sharpbiter, k64fcpu, z80ctrl)
## - SPI tools (mspi_main)
## - CPLD bitstreams for each target machine (requires Quartus Docker)
##
## Credits:
## Copyright: (c) 2019-2026 Philip Smart <philip.smart@net2net.org>
##
## History: March 2026 - Initial global build script.
##
#########################################################################################################
## This source file is free software: you can redistribute it and#or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This source file is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
#########################################################################################################
# Root directory of the FusionX project.
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Directories.
SOFTDIR="${ROOT_DIR}/software"
ASMDIR="${SOFTDIR}/asm"
INCDIR="${ASMDIR}/include"
TMPDIR="${SOFTDIR}/tmp"
ROMDIR="${SOFTDIR}/roms"
TOOLDIR="${SOFTDIR}/tools"
CPLDDIR="${ROOT_DIR}/CPLD/v1.0"
DRVDIR="${SOFTDIR}/FusionX/src/z80drv"
TTYDIR="${SOFTDIR}/FusionX/src/ttymz"
SPIDIR="${SOFTDIR}/FusionX/src/spitools"
BINDIR="${SOFTDIR}/FusionX/bin"
MODDIR="${SOFTDIR}/FusionX/modules"
# Tools.
ASM_JAR="${TOOLDIR}/glass-0.5.1.jar"
CROSS_PREFIX="arm-linux-gnueabihf-"
# Build targets.
SOFTWARE_TARGETS="MZ80A MZ700 MZ2000"
CPLD_TARGETS="MZ80A MZ700 MZ2000 PCW8256"
# Assembly build lists.
BUILDROMLIST="mz2000_ipl_original mz2000_ipl_tzpu mz2000_ipl_fusionx 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="5z009-1b sa-5510_tzfs msbasic_mz80a msbasic_mz700 msbasic_tz40 msbasic_tz80 sharpmz-test"
BUILDTZFSROMLIST="tzfs"
BUILDTZFSMZFLIST="testtz"
CPMVERSIONS="mz700_80c:0 mz80a_80c:1 mz80a_std:2"
# Counters for summary.
PASS=0
FAIL=0
SKIP=0
#-------------------------------------------------------------------------------------------------------
# Helper functions.
#-------------------------------------------------------------------------------------------------------
log_info() { echo "==> $*"; }
log_ok() { echo " [OK] $*"; PASS=$((PASS + 1)); }
log_fail() { echo " [FAIL] $*"; FAIL=$((FAIL + 1)); }
log_skip() { echo " [SKIP] $*"; SKIP=$((SKIP + 1)); }
usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Build all or selected FusionX components."
echo ""
echo "Options:"
echo " --all Build everything (default)"
echo " --asm Build Z80 assembly ROMs only"
echo " --tzfs Build TZFS ROM only"
echo " --cpm Build CP/M only"
echo " --drivers Build kernel modules and user-space apps only"
echo " --spi Build SPI tools only"
echo " --cpld Build CPLD bitstreams only (requires Quartus Docker)"
echo " --clean Clean all build artifacts"
echo " --help Show this help"
echo ""
echo "Software targets: ${SOFTWARE_TARGETS}"
echo "CPLD targets: ${CPLD_TARGETS}"
exit 0
}
#-------------------------------------------------------------------------------------------------------
# Build Z80 Assembly ROMs and MZF files.
#-------------------------------------------------------------------------------------------------------
build_asm_roms() {
log_info "Building Z80 Assembly ROMs and MZF files..."
if ! command -v java &>/dev/null; then
log_skip "Java not found - cannot assemble Z80 ROMs"
return
fi
if [ ! -f "${ASM_JAR}" ]; then
log_skip "GLASS assembler not found at ${ASM_JAR}"
return
fi
mkdir -p "${TMPDIR}" "${ROMDIR}"
for f in ${BUILDROMLIST} ${BUILDMZFLIST}; do
SRCNAME="${f}"
ASMNAME="${f}.asm"
OBJNAME="${f}.obj"
SYMNAME="${f}.sym"
ROMNAME="${f}.rom"
MZFNAME="${f}.mzf"
# MS BASIC variant handling.
case "${SRCNAME}" in
msbasic_mz80a)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 0" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
msbasic_mz700)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 1" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
msbasic_tz40)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 2" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
msbasic_tz80)
ASMNAME="msbasic.asm"
echo "BUILD_VERSION EQU 3" > "${INCDIR}/MSBASIC_BuildVersion.asm"
;;
esac
if java -jar "${ASM_JAR}" "${ASMDIR}/${ASMNAME}" "${TMPDIR}/${OBJNAME}" "${TMPDIR}/${SYMNAME}" -I "${INCDIR}" -I "${ASMDIR}" 2>&1; then
if echo "${BUILDROMLIST}" | grep -qw "${SRCNAME}"; then
cp "${TMPDIR}/${OBJNAME}" "${ROMDIR}/${ROMNAME}"
log_ok "ROM: ${ROMNAME}"
else
cp "${TMPDIR}/${OBJNAME}" "${ROMDIR}/${MZFNAME}"
log_ok "MZF: ${MZFNAME}"
fi
else
log_fail "${SRCNAME}"
fi
done
# Composite MZ-800 ROM.
if [ -f "${ROMDIR}/mz800_1z_013b.rom" ] && [ -f "${ROMDIR}/mz800_cgrom.ori" ] && \
[ -f "${ROMDIR}/mz800_9z_504m.rom" ] && [ -f "${ROMDIR}/mz800_iocs.rom" ]; then
cat "${ROMDIR}/mz800_1z_013b.rom" "${ROMDIR}/mz800_cgrom.ori" \
"${ROMDIR}/mz800_9z_504m.rom" "${ROMDIR}/mz800_iocs.rom" > "${ROMDIR}/mz800_ipl.rom"
log_ok "ROM: mz800_ipl.rom (composite)"
fi
}
#-------------------------------------------------------------------------------------------------------
# Build TZFS ROM for each machine+board combination.
#-------------------------------------------------------------------------------------------------------
build_tzfs() {
log_info "Building TZFS ROMs..."
if ! command -v java &>/dev/null; then
log_skip "Java not found - cannot assemble TZFS"
return
fi
mkdir -p "${TMPDIR}" "${ROMDIR}"
local DEFSFILE="${INCDIR}/tzfs_definitions.asm"
local MACHINES="MZ80A MZ700 MZ2000"
for machine in ${MACHINES}; do
# Set machine target in definitions.
for m in MZ80A MZ700 MZ1500 MZ2000; do
local val=0
[ "${m}" = "${machine}" ] && val=1
sed -i "s/^BUILD_${m}\s\+EQU\s\+[01]/BUILD_${m} EQU ${val}/" "${DEFSFILE}"
done
# Set board to FusionX.
sed -i "s/^BUILD_FUSIONX\s\+EQU\s\+[01]/BUILD_FUSIONX EQU 1/" "${DEFSFILE}"
sed -i "s/^BUILD_PICOZ80\s\+EQU\s\+[01]/BUILD_PICOZ80 EQU 0/" "${DEFSFILE}"
for f in ${BUILDTZFSROMLIST} ${BUILDTZFSMZFLIST}; do
if java -jar "${ASM_JAR}" "${ASMDIR}/${f}.asm" "${TMPDIR}/${f}.obj" "${TMPDIR}/${f}.sym" -I "${INCDIR}" -I "${ASMDIR}" 2>&1; then
local lower_machine=$(echo "${machine}" | tr '[:upper:]' '[:lower:]')
if echo "${BUILDTZFSROMLIST}" | grep -qw "${f}"; then
cp "${TMPDIR}/${f}.obj" "${ROMDIR}/${f}_${lower_machine}_fusionx.rom"
log_ok "TZFS ROM: ${f}_${lower_machine}_fusionx.rom"
else
cp "${TMPDIR}/${f}.obj" "${ROMDIR}/${f}_${lower_machine}_fusionx.mzf"
log_ok "TZFS MZF: ${f}_${lower_machine}_fusionx.mzf"
fi
else
log_fail "TZFS: ${f} (${machine})"
fi
done
done
}
#-------------------------------------------------------------------------------------------------------
# Build CP/M for each version.
#-------------------------------------------------------------------------------------------------------
build_cpm() {
log_info "Building CP/M variants..."
if ! command -v java &>/dev/null; then
log_skip "Java not found - cannot assemble CP/M"
return
fi
mkdir -p "${TMPDIR}" "${ROMDIR}"
for ver in ${CPMVERSIONS}; do
local FILEEXT=$(echo "${ver}" | cut -d: -f1)
local BUILDVER=$(echo "${ver}" | cut -d: -f2)
echo "BUILD_VERSION EQU ${BUILDVER}" > "${INCDIR}/cpm_buildversion.asm"
local all_ok=true
for f in cbios cpm22; do
if java -jar "${ASM_JAR}" "${ASMDIR}/${f}.asm" "${TMPDIR}/${f}.obj" "${TMPDIR}/${f}.sym" -I "${INCDIR}" -I "${ASMDIR}" 2>&1; then
cp "${TMPDIR}/${f}.obj" "${ROMDIR}/${f}.bin"
else
log_fail "CP/M: ${f} (${FILEEXT})"
all_ok=false
fi
done
if ${all_ok}; then
cat "${ROMDIR}/cpm22.bin" "${ROMDIR}/cbios.bin" > "${ROMDIR}/cpm223_${FILEEXT}.bin"
log_ok "CP/M: cpm223_${FILEEXT}.bin"
fi
done
}
#-------------------------------------------------------------------------------------------------------
# Build kernel modules and user-space applications for each target machine.
#-------------------------------------------------------------------------------------------------------
build_drivers() {
log_info "Building kernel modules and user-space applications..."
if ! command -v ${CROSS_PREFIX}gcc &>/dev/null; then
log_skip "ARM cross-compiler (${CROSS_PREFIX}gcc) not found"
return
fi
local KERNEL_DIR="${SOFTDIR}/linux/kernel"
if [ ! -f "${KERNEL_DIR}/Makefile" ]; then
log_skip "Kernel source tree not found at ${KERNEL_DIR}"
return
fi
for target in ${SOFTWARE_TARGETS}; do
log_info " Target: ${target}"
# Build z80drv kernel module + user-space tools.
# Must cd into directory because Makefile uses $(PWD) for kernel path.
if [ -f "${DRVDIR}/Makefile" ]; then
if (cd "${DRVDIR}" && make "${target}" 2>&1); then
(cd "${DRVDIR}" && make install 2>&1) || true
log_ok "z80drv + apps (${target})"
else
log_fail "z80drv (${target})"
fi
(cd "${DRVDIR}" && make clean 2>&1) || true
fi
# Build ttymzdrv kernel module.
if [ -f "${TTYDIR}/Makefile" ]; then
if (cd "${TTYDIR}" && make "${target}" 2>&1); then
(cd "${TTYDIR}" && make install 2>&1) || true
log_ok "ttymzdrv (${target})"
else
log_fail "ttymzdrv (${target})"
fi
(cd "${TTYDIR}" && make clean 2>&1) || true
fi
done
}
#-------------------------------------------------------------------------------------------------------
# Build SPI tools.
#-------------------------------------------------------------------------------------------------------
build_spi() {
log_info "Building SPI tools..."
if ! command -v ${CROSS_PREFIX}gcc &>/dev/null; then
log_skip "ARM cross-compiler (${CROSS_PREFIX}gcc) not found"
return
fi
if [ -f "${SPIDIR}/Makefile" ]; then
if (cd "${SPIDIR}" && make all 2>&1); then
log_ok "SPI tools (mspi_main)"
else
log_fail "SPI tools"
fi
else
log_skip "SPI tools Makefile not found"
fi
}
#-------------------------------------------------------------------------------------------------------
# Build CPLD bitstreams for each target machine.
#-------------------------------------------------------------------------------------------------------
build_cpld() {
log_info "Building CPLD bitstreams..."
if ! command -v quartus_sh &>/dev/null; then
log_skip "Quartus not found in PATH (use Quartus Docker: qp130)"
return
fi
for target in ${CPLD_TARGETS}; do
local BUILDDIR="${CPLDDIR}/${target}/build"
local PROJECT="tzpuFusionX_${target}"
if [ ! -f "${BUILDDIR}/${PROJECT}.qpf" ]; then
log_skip "CPLD: No Quartus project for ${target}"
continue
fi
log_info " Compiling CPLD: ${target}"
if (cd "${BUILDDIR}" && quartus_sh --flow compile "${PROJECT}" 2>&1); then
if [ -f "${BUILDDIR}/output_files/${PROJECT}.pof" ]; then
log_ok "CPLD: ${PROJECT}.pof"
else
log_fail "CPLD: ${target} (no .pof output)"
fi
else
log_fail "CPLD: ${target}"
fi
done
}
#-------------------------------------------------------------------------------------------------------
# Clean all build artifacts.
#-------------------------------------------------------------------------------------------------------
do_clean() {
log_info "Cleaning build artifacts..."
# Assembly temporaries.
rm -f "${TMPDIR}"/*.obj "${TMPDIR}"/*.sym 2>/dev/null
# Driver build artifacts.
if [ -f "${DRVDIR}/Makefile" ]; then
(cd "${DRVDIR}" && make clean 2>/dev/null) || true
fi
if [ -f "${TTYDIR}/Makefile" ]; then
(cd "${TTYDIR}" && make clean 2>/dev/null) || true
fi
if [ -f "${SPIDIR}/Makefile" ]; then
(cd "${SPIDIR}" && make clean 2>/dev/null) || true
fi
log_ok "Clean complete"
}
#-------------------------------------------------------------------------------------------------------
# Main.
#-------------------------------------------------------------------------------------------------------
BUILD_ASM=false
BUILD_TZFS=false
BUILD_CPM=false
BUILD_DRIVERS=false
BUILD_SPI=false
BUILD_CPLD=false
BUILD_ALL=false
DO_CLEAN=false
if [ $# -eq 0 ]; then
BUILD_ALL=true
fi
while [ $# -gt 0 ]; do
case "$1" in
--all) BUILD_ALL=true ;;
--asm) BUILD_ASM=true ;;
--tzfs) BUILD_TZFS=true ;;
--cpm) BUILD_CPM=true ;;
--drivers) BUILD_DRIVERS=true ;;
--spi) BUILD_SPI=true ;;
--cpld) BUILD_CPLD=true ;;
--clean) DO_CLEAN=true ;;
--help|-h) usage ;;
*) echo "Unknown option: $1"; usage ;;
esac
shift
done
echo "========================================"
echo " FusionX Build System"
echo "========================================"
echo ""
if ${DO_CLEAN}; then
do_clean
exit 0
fi
if ${BUILD_ALL} || ${BUILD_ASM}; then build_asm_roms; fi
if ${BUILD_ALL} || ${BUILD_TZFS}; then build_tzfs; fi
if ${BUILD_ALL} || ${BUILD_CPM}; then build_cpm; fi
if ${BUILD_ALL} || ${BUILD_DRIVERS}; then build_drivers; fi
if ${BUILD_ALL} || ${BUILD_SPI}; then build_spi; fi
if ${BUILD_ALL} || ${BUILD_CPLD}; then build_cpld; fi
echo ""
echo "========================================"
echo " Build Summary"
echo " Passed: ${PASS} Failed: ${FAIL} Skipped: ${SKIP}"
echo "========================================"
if [ ${FAIL} -gt 0 ]; then
exit 1
fi
exit 0

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,6 @@
# Select the target host.
#MODEL := MZ2000
#MODEL := MZ1500
#MODEL := MZ700
#MODEL := MZ80A
#MODEL := PCW8XXX
@@ -26,6 +27,7 @@ all:
MZ80A: MODEL_MZ80A
MZ700: MODEL_MZ700
MZ1500: MODEL_MZ1500
MZ2000: MODEL_MZ2000
PCW8XXX: MODEL_PCW8XXX
PCW9XXX: MODEL_PCW9XXX
@@ -34,6 +36,8 @@ MODEL_MZ80A:
$(MAKE) MODEL=MZ80A BUILD_MZ80A
MODEL_MZ700:
$(MAKE) MODEL=MZ700 BUILD_MZ700
MODEL_MZ1500:
$(MAKE) MODEL=MZ1500 BUILD_MZ1500
MODEL_MZ2000:
$(MAKE) MODEL=MZ2000 BUILD_MZ2000
MODEL_PCW8XXX:
@@ -43,6 +47,7 @@ MODEL_PCW9XXX:
BUILD_MZ80A: kmod
BUILD_MZ700: kmod
BUILD_MZ1500: kmod
BUILD_MZ2000: kmod
BUILD_PCW8XXX: kmod
BUILD_PCW9XXX: kmod

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,9 @@
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: v1.0 Feb 2023 - Initial write of the Sharp MZ series hardware interface software.
// v1.01 Mar 2023 - Bug fixes and additional ESC sequence processing.
// v1.02 May 2023 - Updates to accommodate MZ-1500 host.
// v1.2 Jul 2023 - Fixed MZ-1500 ATB Display of lower case characters.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -37,36 +40,47 @@
#endif
// Build time target. Overrides if compile time definition given.
#if defined(TARGET_HOST_MZ700)
#define TARGET_HOST_MZ700 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ2000)
#define TARGET_HOST_MZ2000 1
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ80A)
#if defined(TARGET_HOST_MZ80A)
#define TARGET_HOST_MZ80A 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ700)
#define TARGET_HOST_MZ700 1
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ1500)
#define TARGET_HOST_MZ1500 1
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ2000)
#define TARGET_HOST_MZ2000 1
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_PCW8XXX) || defined(TARGET_HOST_PCW9XXX)
#define TARGET_HOST_PCW 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_MZ2000 0
#else
#define TARGET_HOST_MZ700 0 // Target compilation for an MZ700
#define TARGET_HOST_MZ2000 0 // MZ2000
#define TARGET_HOST_MZ80A 0 // MZ80A
#define TARGET_HOST_MZ1500 0 // MZ1500
#define TARGET_HOST_MZ2000 0 // MZ2000
#define TARGET_HOST_PCW 0 // Amstrad PCW8XXX/9XXX
#endif
// Video display constants.
#define VC_MAX_ROWS 25 // Maximum number of rows on display.
#if defined(TARGET_HOST_MZ700)
#if (TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
#define VC_MAX_COLUMNS 40 // Maximum number of columns on display.
#else
#define VC_MAX_COLUMNS 80 // Maximum number of columns on display.
@@ -78,14 +92,25 @@
#define KEYB_AUTOREPEAT_INITIAL_TIME 800 // Time in milliseconds before starting autorepeat.
#define KEYB_AUTOREPEAT_TIME 100 // Time in milliseconds between auto repeating characters.
#define KEYB_FLASH_TIME 350 // Time in milliseconds for the cursor flash change.
#define CURSOR_THICK_BLOCK 0x43 // Thick block cursor for lower case CAPS OFF
#define CURSOR_BLOCK 0xEF // Block cursor for SHIFT Lock.
#define CURSOR_UNDERLINE 0x3E // Thick underscore for CAPS Lock.
#define MAX_KEYB_BUFFER_SIZE 32 // Maximum size of the keyboard buffer.
#if (TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
#define KEY_SCAN_ROWS 10 // Number of rows on keyboard to scan.
#define CURSOR_CHR_THICK_BLOCK 0x43 // Thick block cursor for Shift Lock.
#define CURSOR_CHR_BLOCK 0xD0 // Block cursor for CAPS Lock.
#define CURSOR_CHR_GRAPH 0xFF // Graphic cursor for GRAPH mode.
#define CURSOR_CHR_UNDERLINE 0x3C // Underline for lower case CAPS OFF.
#elif (TARGET_HOST_MZ2000 == 1)
#define KEY_SCAN_ROWS 12
#define CURSOR_CHR_THICK_BLOCK 0x1E // Thick block cursor for Shift Lock.
#define CURSOR_CHR_BLOCK 0x82 // Block cursor for CAPS Lock.
#define CURSOR_CHR_GRAPH 0x93 // Graphic cursor for GRAPH mode.
#define CURSOR_CHR_UNDERLINE 0x1F // Underline for lower case CAPS OFF.
#endif
// Audio constants.
#define TIMER_8253_MZ80A_FREQ 2000000 // Base input frequency of Timer 0 for square wave generation.
#define TIMER_8253_MZ700_FREQ 768000 // Base input frequency of Timer 0 for square wave generation.
#define TIMER_8253_MZ1500_FREQ 768000 // Base input frequency of Timer 0 for square wave generation.
// Base addresses and sizes within the Video Controller.
#define VIDEO_BASE_ADDR 0x000000 // Base address of the Video Controller.
@@ -134,7 +159,7 @@
#define VMATTR_BG_MASKOUT 0xF8 // Mask to filter out background attribute.
#define VMATTR_BG_MASKIN 0x07 // Mask to filter out background attribute.
// Sharp MZ constants.
// Sharp MZ-80A/700 constants.
//
#define MBADDR_KEYPA 0xE000 // Mainboard 8255 Port A
#define MBADDR_KEYPB 0xE001 // Mainboard 8255 Port B
@@ -155,6 +180,45 @@
#define MBADDR_SCLDSP 0xE200 // Hardware scroll, a read to each location adds 8 to the start of the video access address therefore creating hardware scroll. 00 - reset to power up
#define MBADDR_SCLBASE 0xE2 // High byte scroll base.
#define MBADDR_DSPCTL 0xDFFF // Display 40/80 select register (bit 7)
#define IO_ADDR_E0 0xE0
#define IO_ADDR_E1 0xE1
#define IO_ADDR_E2 0xE2
#define IO_ADDR_E3 0xE3
#define IO_ADDR_E4 0xE4
#define IO_ADDR_E5 0xE5
#define IO_ADDR_E6 0xE6
#define IO_ADDR_E7 0xE7
#define IO_ADDR_E8 0xE8
#define IO_PSG_BOTH 0xE9
#define IO_ADDR_EA 0xEA
#define IO_ADDR_EB 0xEB
#define IO_PCG_PRIO 0xF0
#define IO_PALETTE 0xF1
// Sharp MZ-2000 constants.
#define MBADDR_FDC 0x0D8 // MB8866 IO Region 0D8h - 0DBh
#define MBADDR_FDC_CR MBADDR_FDC + 0x00 // Command Register
#define MBADDR_FDC_STR MBADDR_FDC + 0x00 // Status Register
#define MBADDR_FDC_TR MBADDR_FDC + 0x01 // Track Register
#define MBADDR_FDC_SCR MBADDR_FDC + 0x02 // Sector Register
#define MBADDR_FDC_DR MBADDR_FDC + 0x03 // Data Register
#define MBADDR_FDC_MOTOR MBADDR_FDC + 0x04 // DS[0-3] and Motor control. 4 drives DS= BIT 0 -> Bit 2 = Drive number, 2=1,1=0,0=0 DS0, 2=1,1=0,0=1 DS1 etc
// bit 7 = 1 MOTOR ON LOW (Active)
#define MBADDR_FDC_SIDE MBADDR_FDC + 0x05 // Side select, Bit 0 when set = SIDE SELECT LOW,
#define MBADDR_FDC_DDEN MBADDR_FDC + 0x06 // Double density enable, 0 = double density, 1 = single density disks.
#define MBADDR_PPIA 0x0E0 // 8255 Port A
#define MBADDR_PPIB 0x0E1 // 8255 Port B
#define MBADDR_PPIC 0x0E2 // 8255 Port C
#define MBADDR_PPICTL 0x0E3 // 8255 Control Port
#define MBADDR_PIOA 0x0E8 // Z80 PIO Port A
#define MBADDR_PIOCTLA 0x0E9 // Z80 PIO Port A Control Port
#define MBADDR_PIOB 0x0EA // Z80 PIO Port B
#define MBADDR_PIOCTLB 0x0EB // Z80 PIO Port B Control Port
#define MBADDR_CRTBKCOLR 0x0F4 // Configure external CRT background colour.
#define MBADDR_CRTGRPHPRIO 0x0F5 // Graphics priority register, character or a graphics colour has front display priority.
#define MBADDR_CRTGRPHSEL 0x0F6 // Graphics output select on CRT or external CRT
#define MBADDR_GRAMCOLRSEL 0x0F7 // Graphics RAM colour bank select.
#define MBADDR_GRAMADDRL 0x0C000 // Graphics RAM base address.
//Common character definitions.
#define SCROLL 0x01 // Set scroll direction UP.
@@ -201,7 +265,7 @@
#define CTRL_Z 0x1A
#define ESC 0x1B
#define CTRL_SLASH 0x1C
#define CTRL_LB 0x1B
#define CTRL_LB 0x1
#define CTRL_RB 0x1D
#define CTRL_CAPPA 0x1E
#define CTRL_UNDSCR 0x1F
@@ -216,15 +280,16 @@
#define FUNC8 0x87
#define FUNC9 0x88
#define FUNC10 0x89
#define PAGEUP 0xE0
#define PAGEDOWN 0xE1
#define CURHOMEKEY 0xE2
#define ALPHAGRAPHKEY 0xE3
#define HOTKEY_ORIGINAL 0xE8
#define HOTKEY_RFS80 0xE9
#define HOTKEY_RFS40 0xEA
#define HOTKEY_TZFS 0xEB
#define HOTKEY_LINUX 0xEC
#define HOTKEY_ORIGINAL 0xE0
#define HOTKEY_RFS80 0xE1
#define HOTKEY_RFS40 0xE2
#define HOTKEY_TZFS 0xE3
#define HOTKEY_LINUX 0xE4
#define PAGEUP 0xE8
#define PAGEDOWN 0xE9
#define CURHOMEKEY 0xEA
#define ALPHAGRAPHKEY 0xEB
#define SHIFTLOCKKEY 0xEC
#define NOKEY 0xF0
#define CURSRIGHT 0xF1
#define CURSLEFT 0xF2
@@ -263,6 +328,85 @@
#define READ_HARDWARE() (\
z80io_PRL_Read8(1)\
)
#define WRITE_HARDWARE_IO(__force__,__addr__,__data__)\
{\
if(!ctrl.suspendIO || __force__ == 1)\
{\
SPI_SEND32((uint32_t)__addr__ << 16 | __data__ << 8 | CPLD_CMD_WRITEIO_ADDR);\
}\
}
#define READ_HARDWARE_IO_INIT(__force__,__addr__)\
{\
if(!ctrl.suspendIO || __force__ == 1)\
{\
SPI_SEND32((uint32_t)__addr__ << 16 | 0x00 << 8 | CPLD_CMD_READIO_ADDR);\
while(CPLD_READY() == 0);\
}\
}
#define READ_HARDWARE_IO() (\
z80io_PRL_Read8(1)\
)
// Video memory macros, allows for options based on host hardware - All Sharp MZ series are very similar.
#if (TARGET_HOST_MZ2000 == 1)
// A7 : H 0xD000:0xD7FF or 0xC000:0xFFFF VRAM paged in.
// A6 : H Select Character VRAM (H) or Graphics VRAM (L)
// A5 : H Select 80 char mode, 40 char mode = L
// A4 : L Select all key strobe lines active, for detection of any key press.
// A3-A0: Keyboard strobe lines
#define ENABLE_VIDEO() {\
display.hwVideoMode = (display.hwVideoMode & 0x3F) | 0xC0;\
WRITE_HARDWARE_IO(0, MBADDR_PIOA, display.hwVideoMode);\
}
#define DISABLE_VIDEO() {\
display.hwVideoMode = (display.hwVideoMode & 0x3F);\
WRITE_HARDWARE_IO(0, MBADDR_PIOA, display.hwVideoMode);\
}
#define WRITE_VRAM_CHAR(__addr__,__data__,__xlat__) WRITE_HARDWARE(0,__addr__,__data__)
#define WRITE_VRAM_ATTRIBUTE(__addr__,__data__) {}
#define WRITE_KEYB_STROBE(__data__)\
{\
display.hwVideoMode = (display.hwVideoMode & 0xF0) | 0x10 | (__data__ & 0x0F);\
WRITE_HARDWARE_IO(0, MBADDR_PIOA, display.hwVideoMode );\
}
#define READ_KEYB_INIT() READ_HARDWARE_IO_INIT(0, MBADDR_PIOB)
#define READ_KEYB() READ_HARDWARE_IO()
#elif (TARGET_HOST_MZ1500 ==1)
#define ENABLE_VIDEO() {}
#define DISABLE_VIDEO() {}
#define WRITE_VRAM_CHAR(__addr__,__data__,__xlat__) if(__xlat__ == 1)\
{\
if(islower(__data__))\
{\
WRITE_HARDWARE(0,__addr__,(dispCodeMap[(int)(__data__)].dispCode & 0x7F));\
READ_HARDWARE_INIT(0,(__addr__+0x800));\
WRITE_HARDWARE(0,(__addr__+0x800),(READ_HARDWARE() | 0x80));\
} else\
{\
WRITE_HARDWARE(0,__addr__,dispCodeMap[(int)(__data__)].dispCode);\
READ_HARDWARE_INIT(0,(__addr__+0x800));\
WRITE_HARDWARE(0,(__addr__+0x800),(READ_HARDWARE() & 0x7F));\
}\
} else\
{\
WRITE_HARDWARE(0,__addr__, __data__);\
}
#define WRITE_VRAM_ATTRIBUTE(__addr__,__data__) {\
READ_HARDWARE_INIT(0,(__addr__));\
WRITE_HARDWARE(0,__addr__,((READ_HARDWARE() & 0x80) | (__data__ & 0x7F)));\
}
#define WRITE_KEYB_STROBE(__data__) WRITE_HARDWARE(0, MBADDR_KEYPA, __data__)
#define READ_KEYB_INIT() READ_HARDWARE_INIT(0, MBADDR_KEYPB)
#define READ_KEYB() READ_HARDWARE()
#else
#define ENABLE_VIDEO() {}
#define DISABLE_VIDEO() {}
#define WRITE_VRAM_CHAR(__addr__,__data__,__xlat__) WRITE_HARDWARE(0,__addr__,(__xlat__ == 1 ? dispCodeMap[(int)__data__].dispCode : __data__))
#define WRITE_VRAM_ATTRIBUTE(__addr__,__data__) WRITE_HARDWARE(0,__addr__,__data__)
#define WRITE_KEYB_STROBE(__data__) WRITE_HARDWARE(0, MBADDR_KEYPA, __data__)
#define READ_KEYB_INIT() READ_HARDWARE_INIT(0, MBADDR_KEYPB)
#define READ_KEYB() READ_HARDWARE()
#endif
// Cursor flash mechanism control states.
@@ -316,7 +460,7 @@ typedef struct {
// Mapping table from keyboard scan codes to Sharp MZ keys.
//
typedef struct {
uint8_t scanCode[80];
uint8_t scanCode[KEY_SCAN_ROWS*8];
} t_scanCodeMap;
// Mapping table of a sharp keycode to an ANSI escape sequence string.
@@ -349,16 +493,19 @@ typedef struct {
uint8_t lineWrap; // Wrap line at display edge (1) else stop printing at display edge.
uint8_t useAnsiTerm; // Enable (1) Ansi Terminal Emulator, (0) disable.
uint8_t inDebug; // Prevent recursion when outputting debug information.
// Working variables.
uint8_t hwVideoMode; // Physical configuration of the video control register.
} t_displayBuffer;
// Structure for maintaining the Sharp MZ keyboard parameters and data. Used to retrieve and map a key along with associated
// attributes such as cursor flashing.
//
typedef struct {
uint8_t scanbuf[2][10];
uint8_t keydown[10];
uint8_t keyup[10];
uint8_t keyhold[10];
uint8_t scanbuf[2][KEY_SCAN_ROWS];
uint8_t keydown[KEY_SCAN_ROWS];
uint8_t keyup[KEY_SCAN_ROWS];
uint8_t keyhold[KEY_SCAN_ROWS];
uint32_t holdTimer;
uint8_t breakKey; // Break key pressed.
uint8_t ctrlKey; // Ctrl key pressed.
@@ -398,10 +545,10 @@ typedef struct {
uint8_t setDisplayMode; // Display mode command detected.
uint8_t setExtendedMode; // Extended mode command detected.
uint8_t charbuf[80]; // Storage for the parameter characters as they are received.
uint16_t param[10]; // Parsed paraemters.
uint16_t param[10]; // Parsed parameters.
uint8_t saveRow; // Store the current row when requested.
uint8_t saveCol; // Store the current column when requested.
uint8_t saveDisplayRow; // Store the current display buffer row when requested.
uint8_t saveDisplayRow; // Store the current display buffer row when requested.
} t_AnsiTerm;
// Application execution constants.

View File

@@ -18,6 +18,8 @@
// switching between a Linux session and a Z80 session, the idea
// being the TTY will continue to run within the mirrored framebuffer
// and when reselected, refresh the hardware screen.
// Apr 2023 - v1.1 Updated to include MZ-2000 mode.
// Jul 2023 - v1.2 Updates and bug fixes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -863,8 +865,8 @@ static int __init ttymz_init(void)
mzInit();
// Sign on.
sprintf(buf, "%s %s", DRIVER_DESCRIPTION, DRIVER_VERSION); mzWriteString(0, 0, buf, -1);
sprintf(buf, "%s %s\n", DRIVER_COPYRIGHT, DRIVER_AUTHOR); mzWriteString(0, 1, buf, -1);
sprintf(buf, "%s %s", DRIVER_TITLE, DRIVER_VERSION); mzWriteString(0, 0, buf, -1);
sprintf(buf, "%s %s\n", DRIVER_COPYRIGHT, DRIVER_AUTHOR); mzWriteString(0, 1, buf, -1);
pr_info(DRIVER_DESCRIPTION " " DRIVER_VERSION "\n");

View File

@@ -11,6 +11,8 @@
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 - v1.0 Initial write of the Sharp MZ tty driver software.
// Apr 2023 - v1.1 Updated to include MZ-2000 mode.
// Jul 2023 - v1.2 Updates and bug fixes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -33,15 +35,28 @@
// Constants.
#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "Philip D Smart"
#define DRIVER_AUTHOR "P.D.Smart"
#define DRIVER_DESCRIPTION "Sharp MZ TTY Driver"
#define DRIVER_VERSION "v1.01"
#define DRIVER_VERSION_DATE "Mar 2023"
#define DRIVER_COPYRIGHT "(C) 2018-2023"
#define DRIVER_VERSION "v1.2"
#define DRIVER_VERSION_DATE "July 2023"
#define DRIVER_COPYRIGHT "(C) 2018-23"
#define DEVICE_NAME "ttymz"
#define DRIVER_NAME "SharpMZ_tty"
#define DEBUG_ENABLED 0 // 0 = disabled, 1 .. debug level.
#define ARBITER_NAME "sharpbiter"
#if (TARGET_HOST_MZ80A == 1)
#define DRIVER_TITLE "Sharp MZ-80A TTY"
#elif (TARGET_HOST_MZ700 == 1)
#define DRIVER_TITLE "Sharp MZ-700 TTY"
#elif (TARGET_HOST_MZ1500 == 1)
#define DRIVER_TITLE "Sharp MZ-1500 TTY"
#elif (TARGET_HOST_MZ2000 == 1)
#define DRIVER_TITLE "Sharp MZ-2000 TTY"
#elif (TARGET_HOST_PCW == 1)
#define DRIVER_TITLE "Amstrad PCW-8XXX TTY"
#else
#define DRIVER_MODEL "not defined"
#endif
// Fake UART values
#define MCR_DTR 0x01

View File

@@ -1,4 +1,5 @@
#MODEL := MZ2000
#MODEL := MZ1500
#MODEL := MZ700
#MODEL := MZ80A
#MODEL := PCW8XXX
@@ -23,6 +24,7 @@ all:
MZ80A: MODEL_MZ80A
MZ700: MODEL_MZ700
MZ1500: MODEL_MZ1500
MZ2000: MODEL_MZ2000
PCW8XXX: MODEL_PCW8XXX
PCW9XXX: MODEL_PCW9XXX
@@ -31,6 +33,8 @@ MODEL_MZ80A:
$(MAKE) MODEL=MZ80A BUILD_MZ80A
MODEL_MZ700:
$(MAKE) MODEL=MZ700 BUILD_MZ700
MODEL_MZ1500:
$(MAKE) MODEL=MZ1500 BUILD_MZ1500
MODEL_MZ2000:
$(MAKE) MODEL=MZ2000 BUILD_MZ2000
MODEL_PCW8XXX:
@@ -40,6 +44,7 @@ MODEL_PCW9XXX:
BUILD_MZ80A: sharpbiter k64fcpu kmod z80ctrl
BUILD_MZ700: sharpbiter k64fcpu kmod z80ctrl
BUILD_MZ1500: sharpbiter k64fcpu kmod z80ctrl
BUILD_MZ2000: sharpbiter k64fcpu kmod z80ctrl
BUILD_PCW8XXX: kmod z80ctrl
BUILD_PCW9XXX: kmod z80ctrl

View File

@@ -1,12 +1,13 @@
Development Cycle
-----------------
To avoid changes for one host affecting another the driver is split into seperate hosts containing almost identical code.
The idea, after development is complete, is to merge them into a single drive which autodetects, via the CPLD, the host model
and selects the code accordingly.
z80drv now supports several machines, ie. MZ-80A, MZ-700, MZ-2000, PCW-8256 with more in the pipeline.
Please edit Makefile and set the model prior to changing the Model source. In theory this file will be deleted once the source is
merged.
Please edit Makefile and set the model prior to changing the Model source. Alternatively, isse make with the host name, ie. make MZ80A.
The virtual device concept (ie. an MZ-700 with a tranZPUter SW card) has been incorporated as virtual hardware modules, ie. z80vhw_rfs.c
which adds the RFS card to the MZ-700/MZ-80A. These virtual devices are built and added to the target kernel module dependent on supported
host.
Zeta
----

View File

@@ -19,6 +19,8 @@
// History: Feb 2023 v1.0 - Source copied from zSoft and modified to run as a daemon, stripping
// out all low level control methods.
// v1.01 - Updates to make compatible with the TZFS changes.
// Apr v1.02 - Updates to add MZ-2000 servicing.
// May v1.03 - Updates to add MZ-1500 servicing.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -64,7 +66,7 @@ extern "C" {
#include "z80driver.h"
#include "tzpu.h"
#define VERSION "1.01"
#define VERSION "1.02"
#define AUTHOR "P.D.Smart"
#define COPYRIGHT "(c) 2018-23"
@@ -2328,6 +2330,13 @@ void loadTranZPUterDefaultROMS(uint8_t cpuConfig)
}
break;
case HW_MZ1500:
#if(DEBUG_ENABLED & 0x2)
if(Z80Ctrl->debug >= 2) printf("Loading 1Z_009B\n");
#endif
result = loadTZFS(MZ_ROM_1Z_009B_40C, MZ_MROM_ADDR);
break;
case HW_MZ80B:
//result = loadBIOS(MZ_ROM_MZ80B_IPL, MZ80B, MZ_MROM_ADDR);
result = loadBIOS(MZ_ROM_MZ80B_IPL, MZ_MROM_ADDR);
@@ -2402,6 +2411,7 @@ void processServiceRequest(void)
// Update the service control record address according to memory mode.
//
z80Control.svcControlAddr = getServiceAddr();
printf("Service Addr:%04x\n", z80Control.svcControlAddr);
// Get the command and associated parameters.
copyFromZ80((uint8_t *)&svcControl, z80Control.svcControlAddr, TZSVC_CMD_SIZE, TRANZPUTER);
@@ -2411,7 +2421,7 @@ void processServiceRequest(void)
{
copyFromZ80((uint8_t *)&svcControl.sector, z80Control.svcControlAddr+TZSVC_CMD_SIZE, TZSVC_SECTOR_SIZE, TRANZPUTER);
}
printf("Received command:%02x\n", svcControl.cmd);
//memoryDump((uint32_t)&svcControl, sizeof(svcControl), 5, 8, 0, 0);
// Check this is a valid request.
if(svcControl.result == TZSVC_STATUS_REQUEST)
@@ -2560,7 +2570,7 @@ void processServiceRequest(void)
break;
// Load the MZ-2000 IPL ROM into memory for compatibility switch.
case TZSVC_CMD_LOAD2000IPL:
case TZSVC_CMD_LOAD2KIPL:
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_MZ2000_IPL, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
@@ -2570,6 +2580,21 @@ void processServiceRequest(void)
setZ80CPUFrequency(MZ_2000_CPU_FREQ, 1);
}
break;
// Load the MZ-2000 Basic 1Z001 into memory.
case TZSVC_CMD_LOAD2KBASIC1:
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_ROM_DIR "/" MZ_ROM_MZ2000_1Z001, MZ_MROM_ADDR);
break;
// Load the MZ-2000 Basic 1Z002 into memory.
case TZSVC_CMD_LOAD2KBASIC2:
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_ROM_DIR "/" MZ_ROM_MZ2000_1Z002, MZ_MROM_ADDR);
break;
// Load the MZ-2000 1Z001M Monitor ROM into memory.
case TZSVC_CMD_LOAD2KMON:
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_ROM_DIR "/" MZ_ROM_MZ2000_1Z001M, MZ_MROM_ADDR);
break;
// Load TZFS upon request. This service is for the MZ-80B/MZ-2000 which dont have a monitor BIOS installed and TZFS isnt loaded upon reset but rather through user request.
case TZSVC_CMD_LOADTZFS:
@@ -2709,6 +2734,8 @@ void processServiceRequest(void)
printf("Error: Unsupported Raw SD Write feature.\n");
break;
// Load
// Command to exit from TZFS and return machine to original mode.
case TZSVC_CMD_EXIT:
// Disable secondary frequency.
@@ -2927,6 +2954,8 @@ int main(int argc, char *argv[])
z80Control.hostType = HW_MZ80A;
#elif (TARGET_HOST_MZ700 == 1)
z80Control.hostType = HW_MZ700;
#elif (TARGET_HOST_MZ1500 == 1)
z80Control.hostType = HW_MZ1500;
#elif (TARGET_HOST_MZ2000 == 1)
z80Control.hostType = HW_MZ2000;
#else

View File

@@ -20,6 +20,8 @@
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 v1.0 - Initial write.
// Apr 2023 v1.1 - Updates to include MZ-2000.
// Apr 2023 v1.2 - Updates to include MZ-1500.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -337,12 +339,15 @@ int main(int argc, char *argv[])
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ1500 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ1500;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
@@ -355,10 +360,12 @@ int main(int argc, char *argv[])
ioctlCmd.cmd = IOCTL_CMD_ADD_DEVICE;
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
#elif(TARGET_HOST_MZ1500 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ1500;
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
#endif
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
@@ -381,12 +388,15 @@ int main(int argc, char *argv[])
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ1500 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ1500;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
@@ -418,12 +428,15 @@ int main(int argc, char *argv[])
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ1500 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ1500;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
@@ -449,12 +462,15 @@ int main(int argc, char *argv[])
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ1500 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ1500;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);

View File

@@ -50,6 +50,8 @@
#define OS_BASE_DIR "/apps/FusionX/host/MZ-80A/" // Linux base directory where all the files are stored. On a real tranZPUter this would be the SD card root dir.
#elif (TARGET_HOST_MZ700 == 1)
#define OS_BASE_DIR "/apps/FusionX/host/MZ-700/"
#elif (TARGET_HOST_MZ1500 == 1)
#define OS_BASE_DIR "/apps/FusionX/host/MZ-1500/"
#elif (TARGET_HOST_MZ2000 == 1)
#define OS_BASE_DIR "/apps/FusionX/host/MZ-2000/"
#endif
@@ -203,7 +205,7 @@
// CPLD Configuration constants.
#define HWMODE_MZ80K 0x00 // Hardware mode = MZ80K
#define HWMODE_MZ80C 0x01 // Hardware mode = MZ80C
#define HWMODE_MZ1200 0x02 // Hardware mode = MZ1200
#define HWMODE_MZ1500 0x02 // Hardware mode = MZ1500
#define HWMODE_MZ80A 0x03 // Hardware mode = MZ80A
#define HWMODE_MZ700 0x04 // Hardware mode = MZ700
#define HWMODE_MZ800 0x05 // Hardware mode = MZ800
@@ -321,7 +323,11 @@
// Service request constants.
//
#define TZSVC_CMD_STRUCT_ADDR_TZFS 0x0ED80 // Address of the command structure within TZFS - exists in 64K Block 0.
#if (TARGET_HOST_MZ2000 == 1)
#define TZSVC_CMD_STRUCT_ADDR_TZFS 0x06D80 // Address of the command structure within MZ-2000 IPL Mode
#else
#define TZSVC_CMD_STRUCT_ADDR_TZFS 0x0ED80 // Address of the command structure within TZFS - exists in 64K Block 0.
#endif
#define TZSVC_CMD_STRUCT_ADDR_CPM 0x4F560 // Address of the command structure within CP/M - exists in 64K Block 4.
#define TZSVC_CMD_STRUCT_ADDR_MZ700 0x6FD80 // Address of the command structure within MZ700 compatible programs - exists in 64K Block 6.
#define TZSVC_CMD_STRUCT_ADDR_ZOS 0x11FD80 // 0x7FD80 // Address of the command structure for zOS use, exists in shared memory rather than FPGA. Spans top of block 6 and all of block 7.
@@ -351,7 +357,10 @@
#define TZSVC_CMD_LOAD700BIOS80 0x23 // Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
#define TZSVC_CMD_LOAD80BIPL 0x24 // Service command requesting the MZ-80B IPL is loaded.
#define TZSVC_CMD_LOAD800BIOS 0x25 // Service command requesting that the MZ800 9Z-504M BIOS is loaded.
#define TZSVC_CMD_LOAD2000IPL 0x26 // Service command requesting the MZ-2000 IPL is loaded.
#define TZSVC_CMD_LOAD2KIPL 0x26 // Service command requesting the MZ-2000 IPL is loaded.
#define TZSVC_CMD_LOAD2KBASIC1 0x27 // Service command to load BASIC 1Z-001 for the MZ-2000.
#define TZSVC_CMD_LOAD2KBASIC2 0x28 // Service command to load BASIC 1Z-002 for the MZ-2000.
#define TZSVC_CMD_LOAD2KMON 0x29 // Service command to load Monitor 1Z001M for the MZ-2000 IPL.
#define TZSVC_CMD_LOADTZFS 0x2F // Service command requesting the loading of TZFS. This service is for machines which normally dont have a monitor BIOS. ie. MZ-80B/MZ-2000 and manually request TZFS.
#define TZSVC_CMD_LOADBDOS 0x30 // Service command to reload CPM BDOS+CCP.
#define TZSVC_CMD_ADDSDDRIVE 0x31 // Service command to attach a CPM disk to a drive number.
@@ -379,6 +388,7 @@
#define TZSVC_CMD_SD_WRITESECTOR 0x62 // Service command to provide raw write access to the underlying SD card.
#define TZSVC_CMD_EXIT 0x7F // Service command to terminate TZFS and restart the machine in original mode.
#define TZSVC_DEFAULT_TZFS_DIR "TZFS" // Default directory where TZFS files are stored.
#define TZSVC_DEFAULT_ROM_DIR "ROMS" // Default directory where ROM files are stored.
#define TZSVC_DEFAULT_CPM_DIR "CPM" // Default directory where CPM files are stored.
#define TZSVC_DEFAULT_MZF_DIR "MZF" // Default directory where MZF files are stored.
#define TZSVC_DEFAULT_CAS_DIR "CAS" // Default directory where BASIC CASsette files are stored.
@@ -413,6 +423,7 @@
#define MZ_ROM_1Z_013A_KM_40C "1Z-013A-KM.rom" // Original 40 character Monitor ROM for the Sharp MZ700 with keyboard remapped for the MZ80A.
#define MZ_ROM_1Z_013A_KM_80C "1Z-013A-KM-8.rom" // Original Monitor ROM patched for the Sharp MZ700 with keyboard remapped for the MZ80A and patched for 80 column mode.
#define MZ_ROM_1Z_013A_2000 "1Z-013A-2000.rom" // Original 40 character Monitor ROM for the Sharp MZ700 modified to run on an MZ-2000.
#define MZ_ROM_1Z_009B_40C "1Z-009B.rom" // Original 40 character MZ-1500 Monitor ROM.
#define MZ_ROM_9Z_504M_COMBINED "MZ800_IPL.rom" // Original MZ-800 BIOS which comprises the 1Z_013B BIOS, 9Z_504M IPL, CGROM and IOCS.
#define MZ_ROM_9Z_504M "MZ800_9Z_504M.rom" // Modified MZ-800 9Z_504M IPL to contain a select TZFS option.
#define MZ_ROM_1Z_013B "MZ800_1Z_013B.rom" // Original MZ-800 1Z_013B MZ-700 compatible BIOS.
@@ -423,6 +434,9 @@
#define MZ_ROM_MZ2000_IPL_TZPU "MZ2000_IPL_TZPU.rom" // Modified IPL ROM for the tranZPUter running on the Sharp MZ-2000.
#define MZ_ROM_MZ2000_CGROM "MZ2000_CGROM.rom" // MZ-2000 CGROM.
#define MZ_ROM_TZFS "tzfs.rom" // tranZPUter Filing System ROM.
#define MZ_ROM_MZ2000_1Z001 "mz2000_basic_1z001.rom" // MZ-2000 BASIC 1Z-001.
#define MZ_ROM_MZ2000_1Z002 "mz2000_basic_1z002.rom" // MZ-2000 BASIC 1Z-002.
#define MZ_ROM_MZ2000_1Z001M "mz2000_mon_1z001m.rom" // MZ-2000 BASIC 1Z-002.
// CP/M constants.
//
@@ -470,7 +484,7 @@ enum TARGETS {
enum MACHINE_HW_TYPES {
HW_MZ80K = HWMODE_MZ80K, // Host hardware = MZ-80K.
HW_MZ80C = HWMODE_MZ80C, // Host hardware = MZ-80C.
HW_MZ1200 = HWMODE_MZ1200, // Host hardware = MZ-1200.
HW_MZ1500 = HWMODE_MZ1500, // Host hardware = MZ-1500.
HW_MZ80A = HWMODE_MZ80A, // Host hardware = MZ-80A.
HW_MZ700 = HWMODE_MZ700, // Host hardware = MZ-700.
HW_MZ800 = HWMODE_MZ800, // Host hardware = MZ-800.

View File

@@ -17,6 +17,7 @@
//
// History: Oct 2022 v1.0 - v1.Initial write of the z80 kernel driver software.
// Feb 2023 v1.1 - Extended to allow Rom upload for RFS and other drivers.
// May 2023 v1.2 - Extended to accommodate MZ-1500 host.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -54,7 +55,7 @@
#include <Z80.h>
#include "z80driver.h"
#define VERSION "1.1"
#define VERSION "1.2"
#define AUTHOR "P.D.Smart"
#define COPYRIGHT "(c) 2018-23"
@@ -127,7 +128,7 @@ enum CTRL_COMMANDS {
static t_Z80Ctrl *Z80Ctrl = NULL;
static uint8_t *Z80RAM = NULL;
static uint8_t *Z80ROM = NULL;
static uint32_t *Z80PAGE[MEMORY_MODES];
static uint32_t *Z80PAGE[MEMORY_MODES+MEMORY_SUB_MODES];
static uint8_t memoryPage = 0;
// Method to obtain and return the output screen width.
@@ -436,7 +437,7 @@ int z80load(int fdZ80, char *fileName, uint32_t memLoadAddr, long fileOffset, lo
}
else
{
#if(TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ80A)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
if(mzfHeader.loadAddr > 0x1000)
{
#endif
@@ -446,7 +447,7 @@ int z80load(int fdZ80, char *fileName, uint32_t memLoadAddr, long fileOffset, lo
// Now read in the data.
fread(&Z80RAM[mzfHeader.loadAddr], mzfHeader.fileSize, 1, ptr);
printf("Loaded %s, Size:%04x, Addr:%04x, Exec:%04x\n", fileName, mzfHeader.fileSize, mzfHeader.loadAddr, mzfHeader.execAddr);
#if(TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ80A)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
}
#endif
@@ -459,7 +460,7 @@ int z80load(int fdZ80, char *fileName, uint32_t memLoadAddr, long fileOffset, lo
// Set PC to 2 (NST) which switches to RUN mode and executes at 0000H
ioctlCmd.z80.pc = 2;
#endif
#if(TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ80A)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
// MZ-700 or MZ-80A just use the MZF header exec address.
ioctlCmd.z80.pc = mzfHeader.execAddr;
#endif
@@ -601,6 +602,10 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
}
else if(strcasecmp((char *)param1, "MZ1500") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ1500;
}
else if(strcasecmp((char *)param1, "MZ2000") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
@@ -638,6 +643,10 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
}
else if(strcasecmp((char *)param1, "MZ1500") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ1500;
}
else if(strcasecmp((char *)param1, "MZ2000") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
@@ -1029,7 +1038,7 @@ int main(int argc, char *argv[])
exit(1);
}
// Loop through all the memory mapping pages, each page specifies a 64K mapping block, all memory accesses go through this map.
for(idx=0; idx < MEMORY_MODES; idx++)
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
{
// Try and bind the page, if it doesnt exist, then the pointer will be NULL so it wont be used.
Z80PAGE[idx] = (uint32_t *)mmap(0, ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + (0x1000*(idx+1))), PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);

View File

@@ -13,31 +13,35 @@
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2023 Manuel Sainz de Baranda y Goñi
//
// History: Oct 2022 - v1.0 Initial write of the z80 kernel driver software.
// Jan 2023 - v1.1 Added MZ-2000/MZ-80A modes. There are serious limitations with the
// SSD202 I/O. The I/O Bus appears to run at 72MHz and the GPIO bits
// are split across 2x16 registers per bit. This limits 8bit read
// speed to < 2MB/s, write speed slower due to select signal. Thus it
// is not feasible to run a program in the host memory at full speed.
// Virtual (Kernel) memory is used for all programs and host is only
// accessed for specific reasons, such as the MZ-80A FDD Bios which
// changes according to state of READY signal. I/O operations have to
// use lookahead during fetch cycle to steal time in order to meet timings.
// If SigmaStar make a newer SSD or an alternative becomes available which
// has I/O bus running at 4x speed or has 32bit per cycle GPIO access then
// the design needs to be upgraded to fulfill the idea of running programs
// in host memory at full speed.
// Feb 2023 - v1.2 Added MZ-80A Rom Filing System device driver. This allows the FusionX
// hosted in an MZ-80A to run the original RFS Monitor and software.
// Feb 2023 - v1.3 Added tranZPUter SW device driver. This allows the FusionX hosted
// in any supported host to run TZFS and the updated applications
// such as CP/M, SA-5510 Basic, MS-Basic etc. Adding this device driver
// prepares the ground to add the SOM GPU as the Video emulation of
// the Sharp machines.
// Mar 2023 - v1.4 With the advent of the PCW-8XXX series, seperated distinct machine
// configurations into device driver modules, which are only built
// if same as the target machine. This then allows the z80 driver to be
// a vanilla Z80 or customisations for hosts pulled in.
// History: Oct 2022 - v1.0 Initial write of the z80 kernel driver software.
// Jan 2023 - v1.1 Added MZ-2000/MZ-80A modes. There are serious limitations with the
// SSD202 I/O. The I/O Bus appears to run at 72MHz and the GPIO bits
// are split across 2x16 registers per bit. This limits 8bit read
// speed to < 2MB/s, write speed slower due to select signal. Thus it
// is not feasible to run a program in the host memory at full speed.
// Virtual (Kernel) memory is used for all programs and host is only
// accessed for specific reasons, such as the MZ-80A FDD Bios which
// changes according to state of READY signal. I/O operations have to
// use lookahead during fetch cycle to steal time in order to meet timings.
// If SigmaStar make a newer SSD or an alternative becomes available which
// has I/O bus running at 4x speed or has 32bit per cycle GPIO access then
// the design needs to be upgraded to fulfill the idea of running programs
// in host memory at full speed.
// Feb 2023 - v1.2 Added MZ-80A Rom Filing System device driver. This allows the FusionX
// hosted in an MZ-80A to run the original RFS Monitor and software.
// Feb 2023 - v1.3 Added tranZPUter SW device driver. This allows the FusionX hosted
// in any supported host to run TZFS and the updated applications
// such as CP/M, SA-5510 Basic, MS-Basic etc. Adding this device driver
// prepares the ground to add the SOM GPU as the Video emulation of
// the Sharp machines.
// Mar 2023 - v1.4 With the advent of the PCW-8XXX series, seperated distinct machine
// configurations into device driver modules, which are only built
// if same as the target machine. This then allows the z80 driver to be
// a vanilla Z80 or customisations for hosts pulled in.
// Apr 2023 - v1.4.1 Completed MZ2000 mode to work with arbiter and ttymz.
// May 2023 - v1.5 Added MZ1500 modes.
// Jul 2023 - v1.6 Updated MZ-700 code, adding sub-memory maps to increase page mapping
// speed specifically to enable reliable tape read/write.
//
//
// Notes: See Makefile to enable/disable conditional components
@@ -117,12 +121,15 @@ static DEFINE_MUTEX(Z80DRV_MUTEX);
#if(TARGET_HOST_MZ80A == 1)
#include "z80vhw_mz80a.c"
#endif
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
#include "z80vhw_rfs.c"
#endif
#if(TARGET_HOST_MZ700 == 1)
#include "z80vhw_mz700.c"
#endif
#if(TARGET_HOST_MZ1500 == 1)
#include "z80vhw_mz1500.c"
#endif
#if(TARGET_HOST_MZ2000 == 1)
#include "z80vhw_mz2000.c"
#endif
@@ -161,13 +168,19 @@ static inline void decodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t io
mz700DecodeMemoryMapSetup(address, data, ioFlag, readFlag);
} else
#endif
#if(TARGET_HOST_MZ1500 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ1500)
{
mz1500DecodeMemoryMapSetup(address, data, ioFlag, readFlag);
} else
#endif
#if(TARGET_HOST_MZ2000 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ2000)
{
mz2000DecodeMemoryMapSetup(address, data, ioFlag, readFlag);
} else
#endif
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_RFS)
{
rfsDecodeMemoryMapSetup(address, data, ioFlag, readFlag);
@@ -213,6 +226,12 @@ static inline zuint8 readVirtual(zuint16 address, uint8_t ioFlag)
data = mz700Read(address, ioFlag);
} else
#endif
#if(TARGET_HOST_MZ1500 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ1500)
{
data = mz1500Read(address, ioFlag);
} else
#endif
#if(TARGET_HOST_MZ2000 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ2000)
{
@@ -226,7 +245,7 @@ static inline zuint8 readVirtual(zuint16 address, uint8_t ioFlag)
} else
#endif
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
// RFS only has memory mapped registers.
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_RFS) && ioFlag == 0)
{
@@ -267,6 +286,12 @@ static inline void writeVirtual(zuint16 address, zuint8 data, uint8_t ioFlag)
mz700Write(address, data, ioFlag);
} else
#endif
#if(TARGET_HOST_MZ1500 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ1500)
{
mz1500Write(address, data, ioFlag);
} else
#endif
#if(TARGET_HOST_MZ2000 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ2000)
{
@@ -280,7 +305,7 @@ static inline void writeVirtual(zuint16 address, zuint8 data, uint8_t ioFlag)
} else
#endif
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
// RFS only has memory mapped registers.
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_RFS) && ioFlag == 0)
{
@@ -455,7 +480,11 @@ static zuint8 z80_read(void *context, zuint16 address)
Z_UNUSED(context)
// Only read if the address is in physical RAM.
#if(TARGET_HOST_PCW == 0)
#if(TARGET_HOST_MZ1500 == 1)
// MZ-1500 take into account PCG being active, always go to hardware when active. Cannot use the map because
// this can change during PCG active mode and must be reflected when PCG is deactivated.
if(isPhysical(address) || (Z80Ctrl->pcgMode == 1 && address >= 0xD000))
#elif(TARGET_HOST_PCW == 0)
if(isPhysical(address))
#else
if(isPhysicalHW(address))
@@ -526,6 +555,28 @@ static zuint8 z80_read(void *context, zuint16 address)
Z80Ctrl->keyportTrigger = 0;
}
}
#elif (TARGET_HOST_MZ1500 == 1)
// Keyport data? Store.
if(isHW(address) && address == 0xE001 && (Z80Ctrl->keyportStrobe & 0x0f) == 8)
{
Z80Ctrl->keyportShiftCtrl = (data & 0x40) == 0 ? 0x01 : 0x00;
} else
if(isHW(address) && address == 0xE001 && Z80Ctrl->keyportShiftCtrl == 1)
{
if((Z80Ctrl->keyportStrobe & 0x0f) == 5 && (data & 0xF0) != 0xF0)
{
Z80Ctrl->keyportHotKey = (data & 0x80) == 0 ? HOTKEY_ORIGINAL :
(data & 0x40) == 0 ? HOTKEY_RFS40 :
(data & 0x20) == 0 ? HOTKEY_TZFS :
(data & 0x10) == 0 ? HOTKEY_LINUX : 0x00;
Z80Ctrl->keyportTrigger = Z80Ctrl->keyportHotKey;
} else
{
Z80Ctrl->keyportTrigger = 0;
}
}
#elif (TARGET_HOST_MZ2000 == 1)
#endif
#if(DEBUG_ENABLED & 1)
@@ -545,7 +596,7 @@ static void z80_write(void *context, zuint16 address, zuint8 data)
// Locals.
Z_UNUSED(context)
#if (TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if (TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
// To detect Hotkey presses, we need to store the keyboard strobe data and on keydata read.
if(isHW(address) && address == 0xE000)
{
@@ -560,8 +611,15 @@ static void z80_write(void *context, zuint16 address, zuint8 data)
if(isPhysicalRAM(address))
writeVirtualRAM(address, data);
Z80Ctrl->ioReadAhead = 0;
}
else if(isPhysical(address))
} else
#if(TARGET_HOST_MZ1500 == 1)
// MZ-1500 take into account PCG being active, always go to hardware when active. Cannot use the map because
// this can change during PCG active mode and must be reflected when PCG is deactivated.
if(isPhysical(address) || (Z80Ctrl->pcgMode == 1 && address >= 0xD000))
#else
if(isPhysical(address))
#endif
{
// Commence cycle to write the data to real RAM.
SPI_SEND_32(address, data << 8 | CPLD_CMD_WRITE_ADDR);
@@ -807,6 +865,31 @@ static zuint8 z80_in(void *context, zuint16 port)
// Finally ensure the data from the port is ready and retrieve it.
while(CPLD_READY() == 0);
value = z80io_PRL_Read();
#if (TARGET_HOST_MZ2000 == 1)
// Keyport data? Store.
if((port&0xff) == 0xEA)
{
// If this is the CTRL key row, check the CTRL key.
if((Z80Ctrl->keyportStrobe & 0x1f) == 0x1b)
{
Z80Ctrl->keyportShiftCtrl = (value & 0x08) == 0 ? 0x01 : 0x00;
if(Z80Ctrl->keyportShiftCtrl == 1)
{
Z80Ctrl->keyportTrigger = 0;
}
} else
// If CTRL key is held and we scan the Function Key Row (not all keys mode), then action the pressed key.
if(Z80Ctrl->keyportShiftCtrl == 1 && (Z80Ctrl->keyportStrobe & 0x1f) == 0x10 && (value&0x0f) != 0x0f)
{
Z80Ctrl->keyportHotKey = (value & 0x01) == 0 ? HOTKEY_ORIGINAL :
// (value & 0x02) == 0 ? HOTKEY_RFS40 :
// (value & 0x04) == 0 ? HOTKEY_TZFS :
(value & 0x08) == 0 ? HOTKEY_LINUX : 0x00;
Z80Ctrl->keyportTrigger = Z80Ctrl->keyportHotKey;
}
}
#endif
} else
// Virtual I/O Port.
if(isVirtualIO(port))
@@ -854,6 +937,14 @@ static void z80_out(void *context, zuint16 port, zuint8 value)
// Decode address to action any host specific memory map changes.
decodeMemoryMapSetup(port, value, 1, false);
#endif
#if (TARGET_HOST_MZ2000 == 1)
// To detect Hotkey presses, we need to store the keyboard strobe data and on keydata read.
if((port&0xff) == 0xE8)
{
Z80Ctrl->keyportStrobe = value;
}
#endif
} else
if(isVirtualIO(port))
{
@@ -1007,39 +1098,38 @@ int thread_z80(void * thread_nr)
// Reset pressed?
if(CPLD_RESET())
{
resetZ80();
// Wait for release before restarting CPU.
while(CPLD_RESET());
} else
{
// Update state to indicate request has been actioned.
mutex_lock(&Z80RunModeMutex);
if(Z80RunMode == Z80_STOP) Z80RunMode = Z80_STOPPED;
if(Z80RunMode == Z80_PAUSE) Z80RunMode = Z80_PAUSED;
if(Z80RunMode == Z80_CONTINUE) Z80RunMode = Z80_RUNNING;
if(Z80RunMode == Z80_RUNNING) canRun=1; else canRun=0;
mutex_unlock(&Z80RunModeMutex);
#if (TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
// Hotkey pressed? Bring up user menu.
if(Z80Ctrl->keyportTrigger != 0x00 && Z80Ctrl->keyportTriggerLast == 0)
{
z80menu();
// Send signal to arbiter to change run mode.
sendSignal(Z80Ctrl->arbTask, SIGUSR1);
Z80Ctrl->keyportShiftCtrl = 0;
// Suspend processing until arbiter sets up new environment.
mutex_lock(&Z80RunModeMutex);
Z80RunMode = Z80_STOPPED;
canRun = 0;
mutex_unlock(&Z80RunModeMutex);
}
Z80Ctrl->keyportTriggerLast = Z80Ctrl->keyportTrigger;
#endif
resetZ80();
}
// Update state to indicate request has been actioned.
mutex_lock(&Z80RunModeMutex);
if(Z80RunMode == Z80_STOP) Z80RunMode = Z80_STOPPED;
if(Z80RunMode == Z80_PAUSE) Z80RunMode = Z80_PAUSED;
if(Z80RunMode == Z80_CONTINUE) Z80RunMode = Z80_RUNNING;
if(Z80RunMode == Z80_RUNNING) canRun=1; else canRun=0;
mutex_unlock(&Z80RunModeMutex);
#if (TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1 || TARGET_HOST_MZ2000 == 1)
// Hotkey pressed? Bring up user menu.
if(Z80Ctrl->keyportTrigger != 0x00 && Z80Ctrl->keyportTriggerLast == 0)
{
z80menu();
// Send signal to arbiter to change run mode.
sendSignal(Z80Ctrl->arbTask, SIGUSR1);
Z80Ctrl->keyportShiftCtrl = 0;
// Suspend processing until arbiter sets up new environment.
mutex_lock(&Z80RunModeMutex);
Z80RunMode = Z80_STOPPED;
canRun = 0;
mutex_unlock(&Z80RunModeMutex);
}
Z80Ctrl->keyportTriggerLast = Z80Ctrl->keyportTrigger;
#endif
}
// Release spinlock as we are unloading driver.
@@ -1179,10 +1269,10 @@ static int z80drv_mmap(struct file *filp, struct vm_area_struct *vma)
}
// Another one, as the memory bank page maps are allocated dynamically, need to send a size which indicates which memory block to map. This is done by the size of a memory map
// added to it the map slot as 0x1000 per slot.
else if(size >= ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + 0x1000) && size < ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + (MEMORY_MODES * 0x1000)))
else if(size >= ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + 0x1000) && size < ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((MEMORY_MODES+MEMORY_SUB_MODES) * 0x1000)))
{
// Loop through all the memory page slots, if active and the size is in range, then map the memory to user space.
for(idx=0; idx < MEMORY_MODES; idx++)
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
{
if(size >= ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((idx+1)*0x1000)) && size < ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((idx+2) * 0x1000)))
{
@@ -1376,19 +1466,24 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
mz700SetupMemory(mode);
else
#endif
#if(TARGET_HOST_MZ1500 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ1500)
mz1500SetupMemory(mode);
else
#endif
#if(TARGET_HOST_MZ2000 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_MZ2000)
mz2000SetupMemory(mode);
else
#endif
// RFS board only works in an MZ-80A at present.
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
// RFS board only works on an MZ-80A/MZ-700/MZ-1500 at present.
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_RFS)
rfsSetupMemory(mode);
else
#endif
// tranZPUter operates in all supported Sharp machines.
#if(TARGET_HOST_PCW == 0)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU)
tzpuSetupMemory(mode);
else
@@ -1407,6 +1502,11 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
// Inhibit mode disabled.
Z80Ctrl->inhibitMode = 0;
#if defined(TARGET_HOST_MZ1500)
// Flag to indicate PCG active, all memory accesses from D000:FFFF are sent to hardware.
Z80Ctrl->pcgMode = 0;
#endif
return;
}
@@ -1567,6 +1667,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case 2:
Z80Ctrl->cpuGovernorDelayROM = ROM_DELAY_X2;
Z80Ctrl->cpuGovernorDelayRAM = RAM_DELAY_X2;
pr_info("ROM:%d, RAM:%d\n", Z80Ctrl->cpuGovernorDelayROM, Z80Ctrl->cpuGovernorDelayRAM);
break;
case 4:
@@ -1640,10 +1741,10 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
if(idx < Z80Ctrl->virtualDeviceCnt)
break;
#if(TARGET_HOST_MZ80A == 0 && TARGET_HOST_MZ700 == 0)
#if(TARGET_HOST_MZ80A == 0 && TARGET_HOST_MZ700 == 0 && TARGET_HOST_MZ1500 == 0)
if(ioctlCmd.vdev.device & VIRTUAL_DEVICE_RFS)
{
pr_info("RFS Board currently supported on MZ-80A/MZ-700 Hosts only.\n");
pr_info("RFS Board currently supported on MZ-80A/MZ-700/MZ-1500 Hosts only.\n");
break;
}
#endif
@@ -1665,7 +1766,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
#endif
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
case VIRTUAL_DEVICE_RFS40:
case VIRTUAL_DEVICE_RFS80:
Z80Ctrl->virtualDevice[Z80Ctrl->virtualDeviceCnt++] = ioctlCmd.vdev.device;
@@ -1682,6 +1783,14 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
#endif
#if(TARGET_HOST_MZ1500 == 1)
case VIRTUAL_DEVICE_MZ1500:
Z80Ctrl->virtualDevice[Z80Ctrl->virtualDeviceCnt++] = ioctlCmd.vdev.device;
Z80Ctrl->virtualDeviceBitMap |= ioctlCmd.vdev.device;
mz1500Init(0);
break;
#endif
#if(TARGET_HOST_MZ2000 == 1)
case VIRTUAL_DEVICE_MZ2000:
Z80Ctrl->virtualDevice[Z80Ctrl->virtualDeviceCnt++] = ioctlCmd.vdev.device;
@@ -1756,7 +1865,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
#endif
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if(TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
case VIRTUAL_DEVICE_RFS40:
case VIRTUAL_DEVICE_RFS80:
Z80Ctrl->virtualDeviceBitMap &= ~ioctlCmd.vdev.device;
@@ -1771,6 +1880,13 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
#endif
#if(TARGET_HOST_MZ1500 == 1)
case VIRTUAL_DEVICE_MZ1500:
Z80Ctrl->virtualDeviceBitMap &= ~ioctlCmd.vdev.device;
mz1500Remove();
break;
#endif
#if(TARGET_HOST_MZ2000 == 1)
case VIRTUAL_DEVICE_MZ2000:
Z80Ctrl->virtualDeviceBitMap &= ~ioctlCmd.vdev.device;
@@ -1978,8 +2094,8 @@ static int __init ModuleInit(void)
goto initExit;
}
// Default memory mode is 0, ie. Original. Additional modes may be used by drivers such as the tzpu driver.
Z80Ctrl->memoryMode = 0;
for(idx=0; idx < MEMORY_MODES; idx++)
Z80Ctrl->memoryMode = 0;
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
{
(Z80Ctrl->page[idx]) = NULL;
}
@@ -2032,7 +2148,7 @@ static int __init ModuleInit(void)
Z80Ctrl->ioReadAhead = 0;
Z80Ctrl->ioWriteAhead = 0;
#if (TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1)
#if (TARGET_HOST_MZ80A == 1 || TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1 || TARGET_HOST_MZ2000 == 1)
// Initialse hotkey detection variables.
Z80Ctrl->keyportStrobe = 0x00;
Z80Ctrl->keyportShiftCtrl = 0x00;
@@ -2089,7 +2205,7 @@ static void __exit ModuleExit(void)
}
// Return the memory used for the Z80 'virtual memory' and control variables.
for(idx=0; idx < MEMORY_MODES; idx++)
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
{
if(Z80Ctrl->page[idx] != NULL)
{

View File

@@ -12,9 +12,13 @@
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2023 Manuel Sainz de Baranda y Goñi
//
// History: Oct 2022 - v1.0 Initial write of the z80 kernel driver software.
// Jan 2023 - v1.1 Added MZ-2000/MZ-80A modes.
// Feb 2023 - v1.2 Added RFS virtual driver.
// History: Oct 2022 - v1.0 Initial write of the z80 kernel driver software.
// Jan 2023 - v1.1 Added MZ-2000/MZ-80A modes.
// Feb 2023 - v1.2 Added RFS virtual driver.
// Apr 2023 - v1.4.1 Completed MZ2000 mode to work with arbiter and ttymz.
// May 2023 - v1.5 Added MZ1500 modes.
// Jul 2023 - v1.6 Updated MZ-700 code, adding sub-memory maps to increase page mapping
// speed specifically to enable reliable tape read/write.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -39,26 +43,37 @@
#if defined(TARGET_HOST_MZ700)
#define TARGET_HOST_MZ700 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ2000)
#define TARGET_HOST_MZ2000 1
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ1500)
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ1500 1
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ80A)
#define TARGET_HOST_MZ80A 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_PCW8XXX) || defined(TARGET_HOST_PCW9XXX)
#define TARGET_HOST_PCW 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ1500 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#else
#define TARGET_HOST_MZ700 0 // Target compilation for an MZ700
#define TARGET_HOST_MZ2000 0 // MZ2000
#define TARGET_HOST_MZ1500 0 // MZ1500
#define TARGET_HOST_MZ80A 0 // MZ80A
#define TARGET_HOST_PCW 0 // Amstrad PCW8XXX/9XXX
#endif
@@ -67,8 +82,8 @@
#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "Philip D Smart"
#define DRIVER_DESCRIPTION "Z80 CPU Emulator and Hardware Interface Driver"
#define DRIVER_VERSION "v1.4"
#define DRIVER_VERSION_DATE "Apr 2023"
#define DRIVER_VERSION "v1.6"
#define DRIVER_VERSION_DATE "July 2023"
#define DRIVER_COPYRIGHT "(C) 2018-2023"
#define Z80_VIRTUAL_ROM_SIZE (65536 * 32) // Sized to maximum Kernel contiguous allocation size, 2M which is 4x512K ROMS.
#define Z80_VIRTUAL_RAM_SIZE (65536 * 32) // Sized to maximum Kernel contiguous allocation size, 2M.
@@ -99,11 +114,11 @@
#define IO_TYPE_VIRTUAL_HW 0x40000000
// Hotkeys handled.
#define HOTKEY_ORIGINAL 0xE8
#define HOTKEY_RFS40 0xE9
#define HOTKEY_RFS80 0xEA
#define HOTKEY_TZFS 0xEB
#define HOTKEY_LINUX 0xEC
#define HOTKEY_ORIGINAL 0xE0
#define HOTKEY_RFS40 0xE1
#define HOTKEY_RFS80 0xE2
#define HOTKEY_TZFS 0xE3
#define HOTKEY_LINUX 0xE4
//*********************************************************************************************
// Delay periods for the various hosts, which need adding to the primary opcode fetch in
@@ -144,6 +159,82 @@
#define INSTRUCTION_DELAY_RAM_224MHZ 4
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#endif
#if(DEBUG_ENABLED == 0)
#define INSTRUCTION_DELAY_ROM_3_54MHZ 253
#define INSTRUCTION_DELAY_ROM_7MHZ 126
#define INSTRUCTION_DELAY_ROM_14MHZ 63
#define INSTRUCTION_DELAY_ROM_28MHZ 32
#define INSTRUCTION_DELAY_ROM_56MHZ 16
#define INSTRUCTION_DELAY_ROM_112MHZ 8
#define INSTRUCTION_DELAY_ROM_224MHZ 4
#define INSTRUCTION_DELAY_ROM_448MHZ 1
#define INSTRUCTION_DELAY_RAM_3_54MHZ 240
#define INSTRUCTION_DELAY_RAM_7MHZ 120
#define INSTRUCTION_DELAY_RAM_14MHZ 60
#define INSTRUCTION_DELAY_RAM_28MHZ 30
#define INSTRUCTION_DELAY_RAM_56MHZ 15
#define INSTRUCTION_DELAY_RAM_112MHZ 8
#define INSTRUCTION_DELAY_RAM_224MHZ 4
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#endif
#define INSTRUCTION_EQUIV_FREQ_3_54MHZ 3540000
#define INSTRUCTION_EQUIV_FREQ_7MHZ 7000000
#define INSTRUCTION_EQUIV_FREQ_14MHZ 14000000
#define INSTRUCTION_EQUIV_FREQ_28MHZ 28000000
#define INSTRUCTION_EQUIV_FREQ_56MHZ 56000000
#define INSTRUCTION_EQUIV_FREQ_112MHZ 112000000
#define INSTRUCTION_EQUIV_FREQ_224MHZ 224000000
#define INSTRUCTION_EQUIV_FREQ_448MHZ 448000000
#define INSTRUCTION_GOVERNOR_IO_SKIP 10
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_3_54MHZ,
ROM_DELAY_X2 = INSTRUCTION_DELAY_ROM_7MHZ,
ROM_DELAY_X4 = INSTRUCTION_DELAY_ROM_14MHZ,
ROM_DELAY_X8 = INSTRUCTION_DELAY_ROM_28MHZ,
ROM_DELAY_X16 = INSTRUCTION_DELAY_ROM_56MHZ,
ROM_DELAY_X32 = INSTRUCTION_DELAY_ROM_112MHZ,
ROM_DELAY_X64 = INSTRUCTION_DELAY_ROM_224MHZ,
ROM_DELAY_X128 = INSTRUCTION_DELAY_ROM_448MHZ,
RAM_DELAY_NORMAL = INSTRUCTION_DELAY_RAM_3_54MHZ,
RAM_DELAY_X2 = INSTRUCTION_DELAY_RAM_7MHZ,
RAM_DELAY_X4 = INSTRUCTION_DELAY_RAM_14MHZ,
RAM_DELAY_X8 = INSTRUCTION_DELAY_RAM_28MHZ,
RAM_DELAY_X16 = INSTRUCTION_DELAY_RAM_56MHZ,
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_112MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_224MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_448MHZ,
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_3_54MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_7MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_14MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_28MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_56MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_112MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_224MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_448MHZ,
};
#endif
//
// MZ-1500
#if(TARGET_HOST_MZ1500 == 1)
#if(DEBUG_ENABLED > 0)
#define INSTRUCTION_DELAY_ROM_3_54MHZ 253
#define INSTRUCTION_DELAY_ROM_7MHZ 126
#define INSTRUCTION_DELAY_ROM_14MHZ 63
#define INSTRUCTION_DELAY_ROM_28MHZ 32
#define INSTRUCTION_DELAY_ROM_56MHZ 16
#define INSTRUCTION_DELAY_ROM_112MHZ 8
#define INSTRUCTION_DELAY_ROM_224MHZ 4
#define INSTRUCTION_DELAY_ROM_448MHZ 1
#define INSTRUCTION_DELAY_RAM_3_54MHZ 253
#define INSTRUCTION_DELAY_RAM_7MHZ 126
#define INSTRUCTION_DELAY_RAM_14MHZ 63
#define INSTRUCTION_DELAY_RAM_28MHZ 32
#define INSTRUCTION_DELAY_RAM_56MHZ 16
#define INSTRUCTION_DELAY_RAM_112MHZ 8
#define INSTRUCTION_DELAY_RAM_224MHZ 4
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#endif
#if(DEBUG_ENABLED == 0)
#define INSTRUCTION_DELAY_ROM_3_54MHZ 253
#define INSTRUCTION_DELAY_ROM_7MHZ 126
@@ -310,7 +401,7 @@ enum Z80_INSTRUCTION_DELAY {
#define INSTRUCTION_DELAY_ROM_64MHZ 14
#define INSTRUCTION_DELAY_ROM_128MHZ 7
#define INSTRUCTION_DELAY_ROM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_2MHZ 425
#define INSTRUCTION_DELAY_RAM_2MHZ 429
#define INSTRUCTION_DELAY_RAM_4MHZ 210
#define INSTRUCTION_DELAY_RAM_8MHZ 105
#define INSTRUCTION_DELAY_RAM_16MHZ 52
@@ -510,6 +601,7 @@ enum Z80_INSTRUCTION_DELAY {
// The memory page arrays dont check for allocation due to speed, it is assumed a memory mode page has been allocated and defined prior to the memoryMode
// variable being set to that page.
#define MEMORY_MODES 32 // Maximum number of different memory modes.
#define MEMORY_SUB_MODES 6 // Number of possible alternate memory maps for a given memory mode.
#define MEMORY_PAGE_SIZE 0x10000 // Total size of directly addressable memory.
#define MEMORY_BLOCK_GRANULARITY 0x1 // Any change update MEMORY_BLOCK_SHIFT and mask in MEMORY_BLOCK_MASK
#define MEMORY_BLOCK_SHIFT 0
@@ -573,12 +665,12 @@ enum Z80_INSTRUCTION_DELAY {
}
#define resetZ80() {\
setupMemory(Z80Ctrl->defaultPageMode);\
z80_instant_reset(&Z80CPU);\
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU)\
{\
Z80RunMode = Z80_STOPPED;\
sendSignal(Z80Ctrl->ioTask, SIGUSR1); \
udelay(2000);\
}\
z80_instant_reset(&Z80CPU);\
}
#define IO_ADDR_E0 0xE0
@@ -611,8 +703,9 @@ enum VIRTUAL_DEVICE {
VIRTUAL_DEVICE_NONE = 0x00000000,
VIRTUAL_DEVICE_MZ80A = 0x00000001,
VIRTUAL_DEVICE_MZ700 = 0x00000002,
VIRTUAL_DEVICE_MZ2000 = 0x00000004,
VIRTUAL_DEVICE_PCW = 0x00000008,
VIRTUAL_DEVICE_MZ1500 = 0x00000004,
VIRTUAL_DEVICE_MZ2000 = 0x00000008,
VIRTUAL_DEVICE_PCW = 0x00000010,
VIRTUAL_DEVICE_RFS40 = 0x01000000,
VIRTUAL_DEVICE_RFS80 = 0x02000000,
VIRTUAL_DEVICE_RFS = 0x03000000,
@@ -648,10 +741,10 @@ typedef struct {
// 16bit Input Address -> map -> Pointer to 24bit memory address + type flag.
// -> Pointer+<low bits of address> to 24bit memory address + type flag.
//uint32_t page[MEMORY_BLOCK_SLOTS];
uint32_t *page[MEMORY_MODES];
uint32_t *page[MEMORY_MODES+MEMORY_SUB_MODES];
uint32_t shadowPage[MEMORY_BLOCK_SLOTS]; // Shadow page is for manipulation and backup of an existing page.
// Current memory mode as used by active driver.
// Current memory modes as used by an active driver.
uint8_t memoryMode;
// I/O Page map.
@@ -673,6 +766,11 @@ typedef struct {
// blocks actions which arent allowed during inhibit.
uint8_t inhibitMode;
#if defined(TARGET_HOST_MZ1500)
// Flag to indicate PCG active, all memory accesses from D000:FFFF are sent to hardware.
uint8_t pcgMode;
#endif
// I/O lookahead flags - to overcome SSD202 io slowness.
uint8_t ioReadAhead;
uint8_t ioWriteAhead;

View File

@@ -0,0 +1,606 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80vhw_mz1500.c
// Created: May 2023
// Author(s): Philip Smart
// Description: Z80 Virtual Hardware Driver - MZ-1500
// This file contains the methods used to emulate the original Sharp MZ-1500 without
// any additions, such as the RFS or TZFS boards.
//
// These drivers are intended to be instantiated inline to reduce overhead of a call
// and as such, they are included like header files rather than C linked object files.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: May 2023 v1.0 - Initial write based on the MZ700 module.
// Jul 2023 - v1.6 - Updated MZ-700 code, adding sub-memory maps to increase page mapping
// speed specifically to enable reliable tape read/write. Code changes
// reflected in MZ-1500 module. Addition of MZ-1R18 emulation.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "z80io.h"
#include <gpio_table.h>
#include <asm/io.h>
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
// Device constants.
#define RAM_BASE_ADDR 0x00000 // Base address of the 512K RAM.
// PCW control.
typedef struct {
uint8_t regCtrl; // Control register.
uint8_t loDRAMen; // Lower bank 0000:0FFF DRAM enabled, else monitor.
uint8_t hiDRAMen; // Higher bank D000:FFFF DRAM enabled, else memory mapped I/O.
uint32_t *ramFileMem; // 64K RamFile memory.
uint16_t ramFileAddr; // Address pointer of the MZ-1R18 64K Ram File Board memory.
} t_MZ1500Ctrl;
// RFS Board control.
static t_MZ1500Ctrl MZ1500Ctrl;
//-------------------------------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------------------------------
// Method to setup the memory page config to reflect the PCW configuration.
void mz1500SetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint8_t subMode;
uint32_t idx;
// Setup defaults.
MZ1500Ctrl.regCtrl = 0x00;
MZ1500Ctrl.loDRAMen = 0; // Default is monitor ROM is enabled.
MZ1500Ctrl.hiDRAMen = 0; // Default is memory mapped I/O enabled.
Z80Ctrl->inhibitMode = 0;
// Setup default mode according to run mode, ie. Physical run or Virtual run.
//
if(mode == USE_PHYSICAL_RAM)
{
// Initialise the page pointers and memory to use physical RAM.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_ROM, idx);
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_ROM, idx);
} else
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Cancel refresh as using physical RAM for program automatically refreshes DRAM.
Z80Ctrl->refreshDRAM = 0;
}
else if(mode == USE_VIRTUAL_RAM)
{
// Initialise the page pointers and memory to use virtual RAM.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0xF000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
if((idx&0x00ff) == 0xEA || (idx&0x00ff) == 0xEB)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_VIRTUAL_HW;
} else
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
}
// Setup sub-memory pages to enable rapid switch according to memory bank commands.
for(subMode=0; subMode < MEMORY_SUB_MODES; subMode++)
{
if(Z80Ctrl->page[MEMORY_MODES+subMode] == NULL)
{
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug >=3) pr_info("Allocating memory sub page:%d\n", subMode);
#endif
(Z80Ctrl->page[MEMORY_MODES+subMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
if ((Z80Ctrl->page[MEMORY_MODES+subMode]) == NULL)
{
pr_info("z80drv: failed to allocate memory sub mapping page:%d memory!", subMode);
}
}
// Duplicate current mode into the sub page prior to setting up specific config.
memcpy((uint8_t *)Z80Ctrl->page[MEMORY_MODES+subMode], (uint8_t *)Z80Ctrl->page[0], MEMORY_BLOCK_SLOTS*sizeof(uint32_t));
Z80Ctrl->memoryMode = MEMORY_MODES + subMode;
// MZ1500 memory mode switches.
//
// MZ-1500
// |0000:0FFF|1000:CFFF|D000:FFFF
// ------------------------------
// OUT 0xE0 = |DRAM |DRAM |<last>
// OUT 0xE1 = |<last> |DRAM |DRAM
// OUT 0xE2 = |MONITOR |DRAM |<last>
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
// OUT 0xE5 = |<last> |DRAM |PCG Enable
// OUT 0xE6 = |<last> |DRAM |PCG Disable
//
// Sub-memory page maps:
//
// LOW BANK HIGH BANK PAGE MAP
// DRAM 0
// DRAM MEMORY MAP 1
// Inhibit 2
// DRAM 3
// MONITOR MEMORY MAP 4
// Inhibit 5
//
if(subMode >= 0 && subMode < 3)
{
// Enable lower 4K block as DRAM
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
if(subMode >= 3 && subMode < 6)
{
// Enable lower 4K block as Monitor ROM
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
if(subMode == 0 || subMode == 3)
{
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// MZ-700 mode we only work in first 64K block.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
if(subMode == 1 || subMode == 4)
{
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0xE800; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
for(idx=0xE800; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
if(subMode == 2 || subMode == 5)
{
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
}
}
}
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
}
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
pr_info("MZ-1500 Memory Setup complete.\n");
}
// Method to load a ROM image into the RAM memory.
//
uint8_t mz1500LoadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadSize)
{
// Locals.
uint8_t result = 0;
long noBytes;
struct file *fp;
fp = filp_open(romFileName, O_RDONLY, 0);
if(IS_ERR(fp))
{
pr_info("Error opening ROM Image:%s\n:", romFileName);
result = 1;
} else
{
vfs_llseek(fp, 0, SEEK_SET);
noBytes = kernel_read(fp, fp->f_pos, &Z80Ctrl->ram[loadAddr], loadSize);
if(noBytes < loadSize)
{
pr_info("Short load, ROM Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
}
filp_close(fp,NULL);
}
return(result);
}
// Perform any setup operations, such as variable initialisation, to enable use of this module.
void mz1500Init(uint8_t mode)
{
// Locals.
uint32_t idx;
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug >=3) pr_info("Allocating MZ-1R18 memory\n");
#endif
// Allocate memory for the MZ-1R18 64K Ram File board.
MZ1500Ctrl.ramFileMem = (uint32_t *)kmalloc((65536 * sizeof(uint8_t)), GFP_KERNEL);
if(MZ1500Ctrl.ramFileMem == NULL)
{
pr_info("z80drv: failed to allocate MZ-1R18 Ram File memory!");
}
MZ1500Ctrl.ramFileAddr = 0x0000;
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
// when first powered on.
pr_info("Sync Host RAM to virtual RAM.\n");
for(idx=0; idx < Z80_VIRTUAL_RAM_SIZE; idx++)
{
if(idx >= 0x1000 && idx < 0xD000)
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->ram[idx] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->ram[idx] = 0x00;
}
}
// Original mode, ie. no virtual devices active, copy the host BIOS into the Virtual ROM and initialise remainder of ROM memory
// such that the host behaves as per original spec.
pr_info("Sync Host BIOS to virtual ROM.\n");
for(idx=0; idx < Z80_VIRTUAL_ROM_SIZE; idx++)
{
// Copy BIOS and any add-on ROMS.
if((idx >= 0x0000 && idx < 0x1000) || (idx >= 0xE800 && idx < 0x10000))
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->rom[idx] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->rom[idx] = 0x00;
}
}
// Initial memory config.
mz1500SetupMemory(Z80Ctrl->defaultPageMode);
pr_info("Enabling MZ-1500 driver.\n");
return;
}
// Perform any de-initialisation when the driver is removed.
void mz1500Remove(void)
{
pr_info("Removing MZ-1500 driver.\n");
return;
}
// Method to decode an address and make any system memory map changes as required.
//
static inline void mz1500DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
//uint32_t idx;
// Decoding memory address or I/O address?
if(ioFlag == 0)
{
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3)
{
pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
}
#endif
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
//
// 0000 - 0FFF : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
// 1000 - CFFF : MZ80K/A/700 = RAM
// C000 - CFFF : MZ80A = Monitor ROM (MZ80A rom swap)
// D000 - D7FF : MZ80K/A/700 = VRAM
// D800 - DFFF : MZ1500 = Colour VRAM (MZ1500)
// E000 - E003 : MZ80K/A/700 = 8255
// E004 - E007 : MZ80K/A/700 = 8254
// E008 - E00B : MZ80K/A/700 = LS367
// E00C - E00F : MZ80A = Memory Swap (MZ80A)
// E010 - E013 : MZ80A = Reset Memory Swap (MZ80A)
// E014 : MZ80A/700 = Normat CRT display
// E015 : MZ80A/700 = Reverse CRT display
// E200 - E2FF : MZ80A/700 = VRAM roll up/roll down.
// E800 - EFFF : MZ80K/A/700 = User ROM socket or DD Eprom (MZ1500)
// F000 - F7FF : MZ80K/A/700 = Floppy Disk interface.
// F800 - FFFF : MZ80K/A/700 = Floppy Disk interface.
switch(address)
{
default:
break;
}
} else
{
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3)
{
pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
}
#endif
// Check to see if the memory mode page has been allocated for requested mode, if it hasnt, we need to allocate and then define.
if(((address&0xFF) - 0xE0) >= 0 && ((address&0xFF) - 0xE0) < 7)
{
// MZ1500 memory mode switch.
//
// MZ-1500
// |0000:0FFF|1000:CFFF|D000:FFFF
// ------------------------------
// OUT 0xE0 = |DRAM |DRAM |<last>
// OUT 0xE1 = |<last> |DRAM |DRAM
// OUT 0xE2 = |MONITOR |DRAM |<last>
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
// OUT 0xE5 = |<last> |DRAM |PCG Enable
// OUT 0xE6 = |<last> |DRAM |PCG Disable
//
// Sub-memory page maps:
//
// LOW BANK HIGH BANK PAGE MAP
// DRAM 0
// DRAM MEMORY MAP 1
// Inhibit 2
// DRAM 3
// MONITOR MEMORY MAP 4
// Inhibit 5
//
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
{
case IO_ADDR_E0:
MZ1500Ctrl.loDRAMen = 1;
break;
case IO_ADDR_E1:
MZ1500Ctrl.hiDRAMen = 1;
break;
case IO_ADDR_E2:
MZ1500Ctrl.loDRAMen = 0;
break;
case IO_ADDR_E3:
MZ1500Ctrl.hiDRAMen = 0;
break;
case IO_ADDR_E4:
MZ1500Ctrl.loDRAMen = 0;
MZ1500Ctrl.hiDRAMen = 0;
Z80Ctrl->inhibitMode = 0;
Z80Ctrl->pcgMode = 0;
break;
// PCG Bank Switching.
// 7 6 5 4 3 2 1 0
// 0 0 - CGROM
// 0 1 - PCG Blue Plane
// 1 0 - PCG Red Plane
// 1 1 - PCG Green Plane
case IO_ADDR_E5:
// Any PCG access goes to hardware, set flag and access occurs in primary read/write routines.
Z80Ctrl->pcgMode = 1;
break;
// Disable PCG Bank Switching.
case IO_ADDR_E6:
// Disable PCG mode.
Z80Ctrl->pcgMode = 0;
break;
default:
break;
}
// Setup memory mode based on flag state.
if(Z80Ctrl->inhibitMode)
{
if(MZ1500Ctrl.loDRAMen)
Z80Ctrl->memoryMode = MEMORY_MODES + 2;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 5;
} else
if(MZ1500Ctrl.loDRAMen)
{
if(MZ1500Ctrl.hiDRAMen && !Z80Ctrl->pcgMode)
Z80Ctrl->memoryMode = MEMORY_MODES + 0;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 1;
} else
{
if(MZ1500Ctrl.hiDRAMen && !Z80Ctrl->pcgMode)
Z80Ctrl->memoryMode = MEMORY_MODES + 3;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
}
Z80Ctrl->governorSkip = 0;
} else
if((address&0xff) >= 0xD8 && (address&0xff) < 0xDF)
{
// Do nothing for the Disk interface.
} else
if((address&0xff) >= 0xF4 && (address&0xff) < 0xF8)
{
Z80Ctrl->governorSkip = 0;
} else
{
// Z80Ctrl->governorSkip = 0;
}
}
}
// Method to read from either the memory mapped registers if enabled else the RAM.
static inline uint8_t mz1500Read(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0xFF;
// I/O Operation?
if(ioFlag)
{
switch((address&0xff))
{
// MZ-1R18 Ram File Data Register.
case 0xEA:
data = MZ1500Ctrl.ramFileMem[MZ1500Ctrl.ramFileAddr];
MZ1500Ctrl.ramFileAddr++;
break;
// MZ-1R18 Ram File Control Register.
case 0xEB:
break;
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualMemory(address))
{
// Retrieve data from virtual memory.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
}
break;
}
}
return(data);
}
// Method to handle writes.
static inline void mz1500Write(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
// uint32_t idx;
// I/O Operation?
if(ioFlag)
{
switch((address&0xff))
{
// MZ-1R18 Ram File Data Register.
case 0xEA:
MZ1500Ctrl.ramFileMem[MZ1500Ctrl.ramFileAddr] = data;
MZ1500Ctrl.ramFileAddr++;
break;
// MZ-1R18 Ram File Control Register.
case 0xEB:
MZ1500Ctrl.ramFileAddr = (address & 0xff00) | data;
break;
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualRAM(address))
{
// Update virtual memory.
writeVirtualRAM(address, data);
}
}
}
return;
}

View File

@@ -51,16 +51,50 @@
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
#include "tzpu.h"
// Device constants.
#define RAM_BASE_ADDR 0x00000 // Base address of the 512K RAM.
// System ROM's, either use the host machine ROM or preload a ROM image.
#define ROM_DIR "/apps/FusionX/host/MZ-2000/ROMS/"
#define ROM_IPL_ORIG_FILENAME ROM_DIR "mz2000_ipl.orig"
#define ROM_IPL_ORIG_FILENAME ROM_DIR "mz2000_ipl_original.rom"
#define ROM_IPL_FUSIONX_FILENAME ROM_DIR "mz2000_ipl_fusionx.rom"
#define ROM_IPL_TZPU_FILENAME ROM_DIR "mz2000_ipl_tzpu.rom"
#define ROM_1Z001M_FILENAME ROM_DIR "1Z001M.rom"
// Boot ROM rom load and size definitions.
#define ROM_BOOT_LOAD_ADDR 0x000000
#define ROM_BOOT_SIZE 0x800
#define ROM_1Z001M_LOAD_ADDR 0x000000
#define ROM_ORIG_BOOT_SIZE 0x800
#define ROM_TZPU_BOOT_SIZE 0x1000
#define ROM_FUSIONX_BOOT_SIZE 0x1000
#define ROM_1Z001M_BOOT_SIZE 0x10FB
// Sharp MZ-2000 constants.
#define MBADDR_FDC 0x0D8 // MB8866 IO Region 0D8h - 0DBh
#define MBADDR_FDC_CR MBADDR_FDC + 0x00 // Command Register
#define MBADDR_FDC_STR MBADDR_FDC + 0x00 // Status Register
#define MBADDR_FDC_TR MBADDR_FDC + 0x01 // Track Register
#define MBADDR_FDC_SCR MBADDR_FDC + 0x02 // Sector Register
#define MBADDR_FDC_DR MBADDR_FDC + 0x03 // Data Register
#define MBADDR_FDC_MOTOR MBADDR_FDC + 0x04 // DS[0-3] and Motor control. 4 drives DS= BIT 0 -> Bit 2 = Drive number, 2=1,1=0,0=0 DS0, 2=1,1=0,0=1 DS1 etc
// bit 7 = 1 MOTOR ON LOW (Active)
#define MBADDR_FDC_SIDE MBADDR_FDC + 0x05 // Side select, Bit 0 when set = SIDE SELECT LOW,
#define MBADDR_FDC_DDEN MBADDR_FDC + 0x06 // Double density enable, 0 = double density, 1 = single density disks.
#define MBADDR_PPIA 0x0E0 // 8255 Port A
#define MBADDR_PPIB 0x0E1 // 8255 Port B
#define MBADDR_PPIC 0x0E2 // 8255 Port C
#define MBADDR_PPICTL 0x0E3 // 8255 Control Port
#define MBADDR_PIOA 0x0E8 // Z80 PIO Port A
#define MBADDR_PIOCTLA 0x0E9 // Z80 PIO Port A Control Port
#define MBADDR_PIOB 0x0EA // Z80 PIO Port B
#define MBADDR_PIOCTLB 0x0EB // Z80 PIO Port B Control Port
#define MBADDR_CRTBKCOLR 0x0F4 // Configure external CRT background colour.
#define MBADDR_CRTGRPHPRIO 0x0F5 // Graphics priority register, character or a graphics colour has front display priority.
#define MBADDR_CRTGRPHSEL 0x0F6 // Graphics output select on CRT or external CRT
#define MBADDR_GRAMCOLRSEL 0x0F7 // Graphics RAM colour bank select.
#define MBADDR_GRAMADDRL 0x0C000 // Graphics RAM base address.
// PCW control.
typedef struct {
@@ -84,9 +118,6 @@ void mz2000SetupMemory(enum Z80_MEMORY_PROFILE mode)
// Locals.
uint32_t idx;
// The PCW contains upto 512KB of standard RAM which can be expnded to a physical max of 2MB. The kernel malloc limit is 2MB so the whole virtual
// memory can be mapped into the PCW memory address range.
// Setup defaults.
MZ2000Ctrl.lowMemorySwap = 0x01; // Set memory swap flag to swapped, ie. IPL mode sees DRAM 0x0000:0x7FFF swapped to 0x8000:0xFFFF and ROM pages into 0x0000.
MZ2000Ctrl.highMemoryVRAM = 0x00;
@@ -148,12 +179,22 @@ void mz2000SetupMemory(enum Z80_MEMORY_PROFILE mode)
Z80Ctrl->refreshDRAM = 2;
}
// tranZPUter I/O Ports need to be declared virtual to process locally.
for(idx=0x0000; idx < IO_PAGE_SIZE; idx+=0x0100)
{
Z80Ctrl->iopage[idx+IO_TZ_SVCREQ] = IO_TZ_SVCREQ | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_SYSREQ] = IO_TZ_SYSREQ | IO_TYPE_VIRTUAL_HW;
}
// Ensure 40 char mode is enabled.
// SPI_SEND_32(MBADDR_PIOA, 0x13);
pr_info("MZ-2000 Memory Setup complete.\n");
}
// Method to load a ROM image into the RAM memory.
//
uint8_t mz2000LoadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadSize)
uint8_t mz2000LoadROM(const char* romFileName, uint8_t useROM, uint32_t loadAddr, uint32_t loadSize)
{
// Locals.
uint8_t result = 0;
@@ -168,10 +209,10 @@ uint8_t mz2000LoadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadS
} else
{
vfs_llseek(fp, 0, SEEK_SET);
noBytes = kernel_read(fp, fp->f_pos, &Z80Ctrl->ram[loadAddr], loadSize);
noBytes = kernel_read(fp, fp->f_pos, useROM == 1 ? &Z80Ctrl->rom[loadAddr] : &Z80Ctrl->ram[loadAddr], loadSize);
if(noBytes < loadSize)
{
pr_info("Short load, ROM Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
pr_info("Short load, Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
}
filp_close(fp,NULL);
}
@@ -185,6 +226,35 @@ void mz2000Init(uint8_t mode)
// Locals.
uint32_t idx;
// // Initialise the Z80 PIO/8255 controllers.
// //
// SPI_SEND_32(MBADDR_PPICTL, 0x82); // 8255 A=OUT B=IN C=OUT
// SPI_SEND_32(MBADDR_PPIC, 0x58); // BST=1 NST=0 OPEN=1 WRITE=1
// SPI_SEND_32(MBADDR_PPIA, 0xF7); // All signals inactive, stop cassette.
// SPI_SEND_32(MBADDR_PIOCTLA, 0x0F); // Setup PIO A
// SPI_SEND_32(MBADDR_PIOCTLB, 0xCF); // Setup PIO B
// SPI_SEND_32(MBADDR_PIOCTLB, 0xFF);
//
// // Initialise video hardware.
// //
// SPI_SEND_32(MBADDR_CRTGRPHSEL, 0x00); // Set Graphics VRAM to default, no access to GRAM.
// SPI_SEND_32(MBADDR_CRTBKCOLR, 0x00); // Set background colour on external output to black.
// SPI_SEND_32(MBADDR_GRAMCOLRSEL, 0x01); // Activate Blue graphics RAM bank for graphics operations (this is the default installed bank, red and green are optional).
// SPI_SEND_32(MBADDR_CRTGRPHPRIO, 0x07); // Enable all colour bank graphic output with character priority.
// SPI_SEND_32(MBADDR_PIOA, 0x13); // A7 : H 0xD000:0xD7FF or 0xC000:0xFFFF VRAN paged in.
// // A6 : H Select Character VRAM (H) or Graphics VRAM (L)
// // A5 : H Select 80 char mode, 40 char mode = L
// // A4 : L Select all key strobe lines active, for detection of any key press.
// // A3-A0: Keyboard strobe lines
// SPI_SEND_32(MBADDR_PPIA, 0xFF); // A7 : L APSS Search for next program
// // A6 : L Automatic playback at end of rewind
// // A5 : L Automatic rewind during playback(recording)
// // A4 : L Invert Video
// // A3 : L Stop Cassette
// // A2 : L Play Cassette
// // A1 : L Fast Forward
// // A0 : L Rewind
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
// when first powered on.
@@ -226,8 +296,11 @@ void mz2000Init(uint8_t mode)
// Initial memory config.
mz2000SetupMemory(Z80Ctrl->defaultPageMode);
// mz2000LoadROM(ROM_IPL_ORIG_FILENAME, ROM_BOOT_LOAD_ADDR, ROM_BOOT_SIZE);
// Overwrite the ROM with a modified version (comment out) if needed.
//mz2000LoadROM(ROM_IPL_ORIG_FILENAME, ROM_BOOT_LOAD_ADDR, ROM_ORIG_BOOT_SIZE);
//mz2000LoadROM(ROM_IPL_TZPU_FILENAME, ROM_BOOT_LOAD_ADDR, ROM_TZPU_BOOT_SIZE);
mz2000LoadROM(ROM_IPL_FUSIONX_FILENAME, 1, ROM_BOOT_LOAD_ADDR, ROM_FUSIONX_BOOT_SIZE);
pr_info("Enabling MZ-2000 driver.\n");
return;
@@ -299,6 +372,7 @@ static inline void mz2000DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint
// NST pages in all RAM and resets cpu.
if(data & 0x01)
{
pr_info("NST Reset\n");
MZ2000Ctrl.lowMemorySwap = 0;
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
@@ -320,6 +394,7 @@ static inline void mz2000DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint
// If IPL is active (L), reconfigure memory for power on state.
if((data & 0x01) == 0)
{
pr_info("IPL Reset\n");
mz2000SetupMemory(Z80Ctrl->defaultPageMode);
}
break;
@@ -415,9 +490,28 @@ static inline void mz2000Write(zuint16 address, zuint8 data, uint8_t ioFlag)
// I/O Operation?
if(ioFlag)
{
switch(address)
// Only the lower 8 bits of the I/O address are processed as the upper byte is not used in the Sharp models.
//
switch(address & 0x00FF)
{
case IO_TZ_SVCREQ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug >= 3) pr_info("SVCREQ:%02x\n", data);
#endif
// If a k64f process has registered, send it a service request signal.
pr_info("Sending signal,%02x\n", data);
sendSignal(Z80Ctrl->ioTask, SIGIO);
break;
case IO_TZ_SYSREQ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug >= 3) pr_info("SYSREQ:%02x\n", data);
#endif
break;
default:
pr_info("PORT:%02x\n", data);
break;
}
} else

View File

@@ -12,8 +12,11 @@
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Mar 2023 v1.0 - Initial write based on the RFS hardware module.
// Apr 2023 v1.1 - Updates from the PCW/MZ2000 changes.
// History: Mar 2023 - v1.0 - Initial write based on the RFS hardware module.
// Apr 2023 - v1.1 - Updates from the PCW/MZ2000 changes.
// Jul 2023 - v1.6 - Updated MZ-700 code, adding sub-memory maps to increase page mapping
// speed specifically to enable reliable tape read/write. Addition of
// MZ-1R18 emulation.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -58,6 +61,10 @@
// PCW control.
typedef struct {
uint8_t regCtrl; // Control register.
uint8_t loDRAMen; // Lower bank 0000:0FFF DRAM enabled, else monitor.
uint8_t hiDRAMen; // Higher bank D000:FFFF DRAM enabled, else memory mapped I/O.
uint32_t *ramFileMem; // 64K RamFile memory.
uint16_t ramFileAddr; // Address pointer of the MZ-1R18 64K Ram File Board memory.
} t_MZ700Ctrl;
// RFS Board control.
@@ -72,13 +79,14 @@ static t_MZ700Ctrl MZ700Ctrl;
void mz700SetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint8_t subMode;
uint32_t idx;
// The PCW contains upto 512KB of standard RAM which can be expnded to a physical max of 2MB. The kernel malloc limit is 2MB so the whole virtual
// memory can be mapped into the PCW memory address range.
// Setup defaults.
MZ700Ctrl.regCtrl = 0x00;
MZ700Ctrl.regCtrl = 0x00;
MZ700Ctrl.loDRAMen = 0; // Default is monitor ROM is enabled.
MZ700Ctrl.hiDRAMen = 0; // Default is memory mapped I/O enabled.
Z80Ctrl->inhibitMode = 0;
// Setup default mode according to run mode, ie. Physical run or Virtual run.
//
@@ -150,8 +158,108 @@ void mz700SetupMemory(enum Z80_MEMORY_PROFILE mode)
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
if((idx&0x00ff) == 0xEA || (idx&0x00ff) == 0xEB)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_VIRTUAL_HW;
} else
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
}
// Setup sub-memory pages to enable rapid switch according to memory bank commands.
for(subMode=0; subMode < MEMORY_SUB_MODES; subMode++)
{
if(Z80Ctrl->page[MEMORY_MODES+subMode] == NULL)
{
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug >=3) pr_info("Allocating memory sub page:%d\n", subMode);
#endif
(Z80Ctrl->page[MEMORY_MODES+subMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
if ((Z80Ctrl->page[MEMORY_MODES+subMode]) == NULL)
{
pr_info("z80drv: failed to allocate memory sub mapping page:%d memory!", subMode);
}
}
// Duplicate current mode into the sub page prior to setting up specific config.
memcpy((uint8_t *)Z80Ctrl->page[MEMORY_MODES+subMode], (uint8_t *)Z80Ctrl->page[0], MEMORY_BLOCK_SLOTS*sizeof(uint32_t));
Z80Ctrl->memoryMode = MEMORY_MODES + subMode;
// MZ700 memory mode switch.
//
// MZ-700
// |0000:0FFF|1000:CFFF|D000:FFFF
// ------------------------------
// OUT 0xE0 = |DRAM |DRAM |<last>
// OUT 0xE1 = |<last> |DRAM |DRAM
// OUT 0xE2 = |MONITOR |DRAM |<last>
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
// OUT 0xE5 = |<last> |DRAM |Inhibit
// OUT 0xE6 = |<last> |DRAM |<return to last>
//
// Sub-memory page maps:
//
// LOW BANK HIGH BANK PAGE MAP
// DRAM 0
// DRAM MEMORY MAP 1
// Inhibit 2
// DRAM 3
// MONITOR MEMORY MAP 4
// Inhibit 5
//
if(subMode >= 0 && subMode < 3)
{
// Enable lower 4K block as DRAM
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
if(subMode >= 3 && subMode < 6)
{
// Enable lower 4K block as Monitor ROM
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
if(subMode == 0 || subMode == 3)
{
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// MZ-700 mode we only work in first 64K block.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
if(subMode == 1 || subMode == 4)
{
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0xE800; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
for(idx=0xE800; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
if(subMode == 2 || subMode == 5)
{
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
}
}
}
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
}
@@ -196,6 +304,20 @@ void mz700Init(uint8_t mode)
// Locals.
uint32_t idx;
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug >=3) pr_info("Allocating MZ-1R18 memory\n");
#endif
// Allocate memory for the MZ-1R18 64K Ram File board.
MZ700Ctrl.ramFileMem = (uint32_t *)kmalloc((65536 * sizeof(uint8_t)), GFP_KERNEL);
if(MZ700Ctrl.ramFileMem == NULL)
{
pr_info("z80drv: failed to allocate MZ-1R18 Ram File memory!");
}
MZ700Ctrl.ramFileAddr = 0x0000;
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
// when first powered on.
@@ -230,29 +352,27 @@ void mz700Init(uint8_t mode)
}
}
// Add in a test program to guage execution speed.
#if(TARGET_HOST_MZ700 == 1)
Z80Ctrl->ram[0x1200] = 0x01;
Z80Ctrl->ram[0x1201] = 0x86;
Z80Ctrl->ram[0x1202] = 0xf2;
Z80Ctrl->ram[0x1203] = 0x3e;
Z80Ctrl->ram[0x1204] = 0x15;
Z80Ctrl->ram[0x1205] = 0x3d;
Z80Ctrl->ram[0x1206] = 0x20;
Z80Ctrl->ram[0x1207] = 0xfd;
Z80Ctrl->ram[0x1208] = 0x0b;
Z80Ctrl->ram[0x1209] = 0x78;
Z80Ctrl->ram[0x120a] = 0xb1;
Z80Ctrl->ram[0x120b] = 0x20;
Z80Ctrl->ram[0x120c] = 0xf6;
Z80Ctrl->ram[0x120d] = 0xc3;
Z80Ctrl->ram[0x120e] = 0x00;
Z80Ctrl->ram[0x120f] = 0x00;
#endif
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
// Initial memory config.
mz700SetupMemory(Z80Ctrl->defaultPageMode);
// Add in a test program to guage execution speed.
Z80Ctrl->ram[0x1200] = 0x01;
Z80Ctrl->ram[0x1201] = 0x86;
Z80Ctrl->ram[0x1202] = 0xf2;
Z80Ctrl->ram[0x1203] = 0x3e;
Z80Ctrl->ram[0x1204] = 0x15;
Z80Ctrl->ram[0x1205] = 0x3d;
Z80Ctrl->ram[0x1206] = 0x20;
Z80Ctrl->ram[0x1207] = 0xfd;
Z80Ctrl->ram[0x1208] = 0x0b;
Z80Ctrl->ram[0x1209] = 0x78;
Z80Ctrl->ram[0x120a] = 0xb1;
Z80Ctrl->ram[0x120b] = 0x20;
Z80Ctrl->ram[0x120c] = 0xf6;
Z80Ctrl->ram[0x120d] = 0xc3;
Z80Ctrl->ram[0x120e] = 0x00;
Z80Ctrl->ram[0x120f] = 0x00;
pr_info("Enabling MZ-700 driver.\n");
return;
}
@@ -269,17 +389,17 @@ void mz700Remove(void)
static inline void mz700DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
uint32_t idx;
//uint32_t idx;
// Decoding memory address or I/O address?
if(ioFlag == 0)
{
// #if(DEBUG_ENABLED & 1)
// if(Z80Ctrl->debug >= 2)
// {
// pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
// }
// #endif
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3)
{
pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
}
#endif
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
//
@@ -306,116 +426,97 @@ static inline void mz700DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8
}
} else
{
// #if(DEBUG_ENABLED & 1)
// if(Z80Ctrl->debug >= 2)
// {
// pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
// }
// #endif
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3)
{
pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
}
#endif
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
// Check to see if the memory mode page has been allocated for requested mode, if it hasnt, we need to allocate and then define.
if(((address&0xFF) - 0xE0) >= 0 && ((address&0xFF) - 0xE0) < 7)
{
// MZ700 memory mode switch.
//
//
// MZ-700
// |0000:0FFF|1000:CFFF|D000:FFFF
// ------------------------------
// OUT 0xE0 = |DRAM | |
// OUT 0xE1 = | | |DRAM
// OUT 0xE2 = |MONITOR | |
// OUT 0xE3 = | | |Memory Mapped I/O
// OUT 0xE0 = |DRAM |DRAM |<last>
// OUT 0xE1 = |<last> |DRAM |DRAM
// OUT 0xE2 = |MONITOR |DRAM |<last>
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
// OUT 0xE5 = | | |Inhibit
// OUT 0xE6 = | | |<return>
//
// <return> = Return to the state prior to the complimentary command being invoked.
// Enable lower 4K block as DRAM
case IO_ADDR_E0:
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
break;
// OUT 0xE5 = |<last> |DRAM |Inhibit
// OUT 0xE6 = |<last> |DRAM |<return to last>
//
// Sub-memory page maps:
//
// LOW BANK HIGH BANK PAGE MAP
// DRAM 0
// DRAM MEMORY MAP 1
// Inhibit 2
// DRAM 3
// MONITOR MEMORY MAP 4
// Inhibit 5
//
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
{
case IO_ADDR_E0:
MZ700Ctrl.loDRAMen = 1;
break;
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
case IO_ADDR_E1:
if(!Z80Ctrl->inhibitMode)
{
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// MZ-700 mode we only work in first 64K block.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
break;
// Enable MOnitor ROM in lower 4K block
case IO_ADDR_E2:
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
break;
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
case IO_ADDR_E3:
if(!Z80Ctrl->inhibitMode)
{
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
}
break;
case IO_ADDR_E1:
MZ700Ctrl.hiDRAMen = 1;
break;
// Reset to power on condition memory map.
case IO_ADDR_E4:
// Lower 4K set to Monitor ROM.
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
if(!Z80Ctrl->inhibitMode)
{
// Upper 12K to hardware.
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
}
break;
case IO_ADDR_E2:
MZ700Ctrl.loDRAMen = 0;
break;
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
case IO_ADDR_E5:
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
backupMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
}
Z80Ctrl->inhibitMode = 1;
break;
case IO_ADDR_E3:
MZ700Ctrl.hiDRAMen = 0;
break;
// Restore D000-FFFF to its original state.
case IO_ADDR_E6:
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
restoreMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
}
Z80Ctrl->inhibitMode = 0;
break;
case IO_ADDR_E4:
MZ700Ctrl.loDRAMen = 0;
MZ700Ctrl.hiDRAMen = 0;
Z80Ctrl->inhibitMode = 0;
break;
// Port is not a memory management port.
default:
break;
case IO_ADDR_E5:
Z80Ctrl->inhibitMode = 1;
break;
case IO_ADDR_E6:
Z80Ctrl->inhibitMode = 0;
break;
default:
break;
}
// Setup memory mode based on flag state.
if(Z80Ctrl->inhibitMode)
{
if(MZ700Ctrl.loDRAMen)
Z80Ctrl->memoryMode = MEMORY_MODES + 2;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 5;
} else
if(MZ700Ctrl.loDRAMen)
{
if(MZ700Ctrl.hiDRAMen)
Z80Ctrl->memoryMode = MEMORY_MODES + 0;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 1;
} else
{
if(MZ700Ctrl.hiDRAMen)
Z80Ctrl->memoryMode = MEMORY_MODES + 3;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
}
}
}
}
@@ -429,8 +530,18 @@ static inline uint8_t mz700Read(zuint16 address, uint8_t ioFlag)
// I/O Operation?
if(ioFlag)
{
switch(address)
switch((address&0xff))
{
// MZ-1R18 Ram File Data Register.
case 0xEA:
data = MZ700Ctrl.ramFileMem[MZ700Ctrl.ramFileAddr];
MZ700Ctrl.ramFileAddr++;
break;
// MZ-1R18 Ram File Control Register.
case 0xEB:
break;
default:
break;
}
@@ -460,8 +571,19 @@ static inline void mz700Write(zuint16 address, zuint8 data, uint8_t ioFlag)
// I/O Operation?
if(ioFlag)
{
switch(address)
switch((address&0xff))
{
// MZ-1R18 Ram File Data Register.
case 0xEA:
MZ700Ctrl.ramFileMem[MZ700Ctrl.ramFileAddr] = data;
MZ700Ctrl.ramFileAddr++;
break;
// MZ-1R18 Ram File Control Register.
case 0xEB:
MZ700Ctrl.ramFileAddr = (address & 0xff00) | data;
break;
default:
break;
}

View File

@@ -194,6 +194,9 @@ void pcwInit(uint8_t mode)
Z80Ctrl->ram[0] = 0x00;
Z80Ctrl->ram[1] = 0x00;
// Initial memory config.
pcwSetupMemory(Z80Ctrl->defaultPageMode);
pr_info("Enabling PCW-%s driver.\n", mode == 0 ? "8256" : "9256");
return;
}
@@ -297,7 +300,7 @@ pr_info("VORIGIN:%02x\n", data);
pr_info("SCREENATTR:%02x\n", data);
break;
case IO_GACMD:
pr_info("GACMD:%02x\n", data);
//pr_info("GACMD:%02x\n", data);
break;
default:

View File

@@ -95,6 +95,8 @@
#define ROM_DIR "/apps/FusionX/host/MZ-80A/RFS/"
#elif(TARGET_HOST_MZ700 == 1)
#define ROM_DIR "/apps/FusionX/host/MZ-700/RFS/"
#elif(TARGET_HOST_MZ1500 == 1)
#define ROM_DIR "/apps/FusionX/host/MZ-1500/RFS/"
#else
#error "Unknown host configured."
#endif
@@ -106,20 +108,23 @@
#define ROM_USER_I_80C_FILENAME ROM_DIR "USER_ROM_256_80c.bin"
#define ROM_USER_II_80C_FILENAME ROM_DIR "USER_ROM_II_256_80c.bin"
#define ROM_USER_III_80C_FILENAME ROM_DIR "USER_ROM_III_256_80c.bin"
#define ROM_MZ_1E05_FILENAME ROM_DIR "mz-1e05.bin"
// RFS Board ROM rom load and size definitions.
#define ROM_MROM_LOAD_ADDR 0x000000
#define ROM_USER_I_LOAD_ADDR 0x080000
#define ROM_USER_II_LOAD_ADDR 0x100000
#define ROM_USER_III_LOAD_ADDR 0x180000
#define ROM_MZ_1E05_ADDR ((Z80_VIRTUAL_ROM_SIZE-0x10000)+0xF000)
#define ROM_MROM_SIZE 0x80000
#define ROM_USER_I_SIZE 0x80000
#define ROM_USER_II_SIZE 0x80000
#define ROM_USER_III_SIZE 0x80000
#define ROM_MZ_1E05_SIZE 0x1000
// SD Drive constants.
#define SD_DIR "/apps/FusionX/host/MZ-80A/RFS/"
#define SD_CARD_FILENAME SD_DIR "SHARP_MZ80A_RFS_CPM_IMAGE_1.img"// SD Card Binary Image.
#define SD_CARD_FILENAME SD_DIR "SHARP_MZ80A_RFS_CPM_IMAGE_1.img" // SD Card Binary Image.
// MMC/SD command (SPI mode)
#define CMD0 0x40 + 0 // GO_IDLE_STATE
@@ -255,9 +260,14 @@ void rfsSetupMemory(enum Z80_MEMORY_PROFILE mode)
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
#if (TARGET_HOST_MZ700 == 1)
#if (TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
#if (TARGET_HOST_MZ1500 == 1)
// MZ-1500, E4 reset closes the PCG access.
Z80Ctrl->pcgMode = 0;
#endif
#endif
// No I/O Ports on the RFS board.
@@ -311,10 +321,16 @@ void rfsInit(uint8_t mode80c)
while(CPLD_READY() == 0);
Z80Ctrl->rom[idx+(Z80_VIRTUAL_ROM_SIZE-0x10000)] = z80io_PRL_Read8(1);
}
rfsLoadROM(ROM_MZ_1E05_FILENAME, ROM_MZ_1E05_ADDR, ROM_MZ_1E05_SIZE);
#if (TARGET_HOST_MZ700 == 1)
#if (TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ1500 == 1)
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
#if (TARGET_HOST_MZ1500 == 1)
// MZ-1500, E4 reset closes the PCG access.
Z80Ctrl->pcgMode = 0;
#endif
#endif
pr_info("Enabling RFS(%d) driver.\n", mode80c == 1 ? 80 : 40);

View File

@@ -16,8 +16,11 @@
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 v1.0 - Initial write based on the tranZPUter SW hardware.
// Apr 2023 v1.1 - Updates & bug fixes.
// History: Feb 2023 - v1.0 - Initial write based on the tranZPUter SW hardware.
// Apr 2023 - v1.1 - Updates & bug fixes.
// Jul 2023 - v1.6 - Updated MZ-700 code, adding sub-memory maps to increase page mapping
// speed specifically to enable reliable tape read/write.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -68,6 +71,8 @@ typedef struct {
uint8_t regCpuInfo; // Internal FPGA CPU information register.
uint8_t regCpldCfg; // Internal CPLD config register.
uint8_t regCpldInfo; // Internal CPLD information register.
uint8_t loDRAMen; // Lower bank 0000:0FFF DRAM enabled, else monitor.
uint8_t hiDRAMen; // Higher bank D000:FFFF DRAM enabled, else memory mapped I/O.
} t_TZPUCtrl;
// TZPU Board control.
@@ -147,10 +152,12 @@ void tzpuSetupMemory(enum Z80_MEMORY_PROFILE mode)
#if(TARGET_HOST_MZ2000 == 1)
TZPUCtrl.regCpldInfo = (CPLD_VERSION << 4) | (CPLD_HAS_FPGA_VIDEO << 3) | HWMODE_MZ2000;
#endif
TZPUCtrl.regCpldCfg = 0x00; // Not used, as no CPLD available, but need to store/return value if addressed.
TZPUCtrl.regCpldCfg = 0x00; // Not used, as no CPLD available, but need to store/return value if addressed.
TZPUCtrl.loDRAMen = 0; // Default is monitor ROM is enabled.
TZPUCtrl.hiDRAMen = 0; // Default is memory mapped I/O enabled.
// Default memory mode, TZFS.
Z80Ctrl->memoryMode = TZMM_ORIG;
Z80Ctrl->memoryMode = TZMM_TZFS;
// Reset IO mapping.
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
@@ -246,7 +253,7 @@ void tzpuRemove(void)
uint32_t idx;
// Go through and clear all memory maps, leave the original page in slot 0.
for(idx=1; idx < MEMORY_MODES; idx++)
for(idx=1; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
{
if(Z80Ctrl->page[idx] != NULL)
{
@@ -267,17 +274,18 @@ void tzpuRemove(void)
static inline void tzpuDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
uint32_t idx;
//uint32_t idx;
// I/O or Memory?
if(ioFlag == 0)
{
// #if(DEBUG_ENABLED & 1)
// if(Z80Ctrl->debug >= 2)
// {
// pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
// }
// #endif
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3)
{
pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
}
#endif
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
//
@@ -305,116 +313,87 @@ static inline void tzpuDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_
} else
// I/O Decoding.
{
// #if(DEBUG_ENABLED & 1)
// if(Z80Ctrl->debug >= 2)
// {
// pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
// }
// #endif
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3)
{
pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
}
#endif
// Check to see if the memory mode page has been allocated for requested mode, if it hasnt, we need to allocate and then define.
if(((address&0xFF) - 0xE0) >= 0 && ((address&0xFF) - 0xE0) < MEMORY_SUB_MODES)
{
// MZ700 memory mode switch.
//
//
// MZ-700
// |0000:0FFF|1000:CFFF|D000:FFFF
// ------------------------------
// OUT 0xE0 = |DRAM | |
// OUT 0xE1 = | | |DRAM
// OUT 0xE2 = |MONITOR | |
// OUT 0xE3 = | | |Memory Mapped I/O
// OUT 0xE0 = |DRAM |DRAM |<last>
// OUT 0xE1 = |<last> |DRAM |DRAM
// OUT 0xE2 = |MONITOR |DRAM |<last>
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
// OUT 0xE5 = | | |Inhibit
// OUT 0xE6 = | | |<return>
//
// <return> = Return to the state prior to the complimentary command being invoked.
// Enable lower 4K block as DRAM
case IO_ADDR_E0:
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
break;
// OUT 0xE5 = |<last> |DRAM |Inhibit
// OUT 0xE6 = |<last> |DRAM |<return to last>
//
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
{
case IO_ADDR_E0:
TZPUCtrl.loDRAMen = 1;
break;
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
case IO_ADDR_E1:
if(!Z80Ctrl->inhibitMode)
{
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// MZ-700 mode we only work in first 64K block.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
break;
// Enable MOnitor ROM in lower 4K block
case IO_ADDR_E2:
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
break;
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
case IO_ADDR_E3:
if(!Z80Ctrl->inhibitMode)
{
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
}
break;
case IO_ADDR_E1:
TZPUCtrl.hiDRAMen = 1;
break;
// Reset to power on condition memory map.
case IO_ADDR_E4:
// Lower 4K set to Monitor ROM.
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
if(!Z80Ctrl->inhibitMode)
{
// Upper 12K to hardware.
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
}
break;
case IO_ADDR_E2:
TZPUCtrl.loDRAMen = 0;
break;
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
case IO_ADDR_E5:
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
backupMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
}
Z80Ctrl->inhibitMode = 1;
break;
case IO_ADDR_E3:
TZPUCtrl.hiDRAMen = 0;
break;
// Restore D000-FFFF to its original state.
case IO_ADDR_E6:
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
restoreMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
}
Z80Ctrl->inhibitMode = 0;
break;
case IO_ADDR_E4:
TZPUCtrl.loDRAMen = 0;
TZPUCtrl.hiDRAMen = 0;
Z80Ctrl->inhibitMode = 0;
break;
// Port is not a memory management port.
default:
break;
case IO_ADDR_E5:
Z80Ctrl->inhibitMode = 1;
break;
case IO_ADDR_E6:
Z80Ctrl->inhibitMode = 0;
break;
default:
break;
}
// Setup memory mode based on flag state.
if(Z80Ctrl->inhibitMode)
{
if(TZPUCtrl.loDRAMen)
Z80Ctrl->memoryMode = MEMORY_MODES + 2;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 5;
} else
if(TZPUCtrl.loDRAMen)
{
if(TZPUCtrl.hiDRAMen)
Z80Ctrl->memoryMode = MEMORY_MODES + 0;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 1;
} else
{
if(TZPUCtrl.hiDRAMen)
Z80Ctrl->memoryMode = MEMORY_MODES + 3;
else
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
}
}
}
}
@@ -493,6 +472,7 @@ static inline uint8_t tzpuRead(zuint16 address, uint8_t ioFlag)
static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals
uint8_t subMode;
uint32_t idx;
// The tranZPUter board, in order to autoboot and use valuable space for variables, allows writing into the User ROM
@@ -925,6 +905,95 @@ static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
}
}
// Memory map now created/switched.
// Allocate/populate the sub-memory maps for this mode. TZFS currently uses sub-memory modes for MZ-700 page banking.
if(Z80Ctrl->memoryMode == TZMM_TZFS)
{
for(subMode=0; subMode < MEMORY_SUB_MODES; subMode++)
{
if(Z80Ctrl->page[MEMORY_MODES+subMode] == NULL)
{
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug >=3) pr_info("Allocating memory sub page:%d\n", subMode);
#endif
pr_info("Allocating memory sub page:%d,%d\n", subMode, (MEMORY_BLOCK_SLOTS*sizeof(uint32_t)));
(Z80Ctrl->page[MEMORY_MODES+subMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
if ((Z80Ctrl->page[MEMORY_MODES+subMode]) == NULL)
{
pr_info("z80drv: failed to allocate memory sub mapping page:%d memory!", subMode);
}
}
// Duplicate current mode into the sub page prior to setting up specific config.
memcpy((uint8_t *)Z80Ctrl->page[MEMORY_MODES+subMode], (uint8_t *)Z80Ctrl->page[(data & (MEMORY_MODES - 1))], MEMORY_BLOCK_SLOTS*sizeof(uint32_t));
Z80Ctrl->memoryMode = MEMORY_MODES + subMode;
TZPUCtrl.loDRAMen = 0;
TZPUCtrl.hiDRAMen = 0;
Z80Ctrl->inhibitMode = 0;
// MZ700 memory mode switch.
//
// MZ-700
// |0000:0FFF|1000:CFFF|D000:FFFF
// ------------------------------
// OUT 0xE0 = |DRAM |DRAM |<last>
// OUT 0xE1 = |<last> |DRAM |DRAM
// OUT 0xE2 = |MONITOR |DRAM |<last>
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
// OUT 0xE5 = |<last> |DRAM |Inhibit
// OUT 0xE6 = |<last> |DRAM |<return to last>
//
// Sub-memory page maps:
//
// LOW BANK HIGH BANK PAGE MAP
// DRAM 0
// DRAM MEMORY MAP 1
// Inhibit 2
// DRAM 3
// MONITOR MEMORY MAP 4
// Inhibit 5
//
if(subMode >= 0 && subMode < 3)
{
// Enable lower 4K block as DRAM
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
if(subMode == 0 || subMode == 3)
{
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// MZ-700 mode we only work in first 64K block.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
if(subMode == 1 || subMode == 4)
{
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
}
if(subMode == 2 || subMode == 5)
{
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
}
}
}
}
Z80Ctrl->memoryMode = (data & (MEMORY_MODES - 1));
break;
case IO_TZ_SETXMHZ:

1
software/asm/1Z001M.asm Symbolic link
View File

@@ -0,0 +1 @@
/srv2/SharpSoft/MZ-2000/ASM/1Z001M.asm

3303
software/asm/1z-013a-km.asm Normal file

File diff suppressed because it is too large Load Diff

25545
software/asm/5z009-1b.asm Normal file

File diff suppressed because it is too large Load Diff

1658
software/asm/SFD700.asm Normal file

File diff suppressed because it is too large Load Diff

2298
software/asm/asm.asm Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1615
software/asm/cbios.asm Normal file

File diff suppressed because it is too large Load Diff

3908
software/asm/cbiosII.asm Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: cpm22-bios.asm
;- Created: January 2020
;- Author(s): Philip Smart
;- Description: CPM BIOS for CPM v2.23 on the Sharp MZ80A with the Rom Filing System.
;- Most of the code is stored in the ROM based CBIOS which is part of the
;- Rom Filing System upgrade. Declarations in this file are for tables
;- which need to reside in RAM.
;-
;- Credits: Some of the comments and parts of the deblocking/blocking algorithm come from the
; Z80-MBC2 project, (C) SuperFabius.
;- Copyright: (c) 2020 Philip Smart <philip.smart@net2net.org>
;-
;- History: January 2020 - Initial creation.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
ORG CPMBIOS
; All CBIOS code, tables and variables are now stored in the cbios.asm and cbiosII.asm as a seperate assembled
; binary.

3764
software/asm/cpm22.asm Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
BUILD_VERSION EQU 3

View File

@@ -0,0 +1 @@
BUILD_VERSION EQU 2

View File

@@ -0,0 +1,536 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: CPM_Definitions.asm
;- Created: January 2020
;- Author(s): Philip Smart
;- Description: Sharp MZ series CPM v2.23
;- Definitions for the Sharp MZ80A CPM v2.23 OS used in the RFS
;-
;- Credits:
;- Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
;-
;- History: Jan 2020 - Initial version.
; May 2020 - Advent of the new RFS PCB v2.0, quite a few changes to accommodate the
; additional and different hardware. The SPI is now onboard the PCB and
; not using the printer interface card.
; May 2020 - Cut from the RFS version of CPM for the tranZPUter SW board.
;- Apr 2021 - Updates backported from the RFS version of CPM.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;-----------------------------------------------
; Features.
;-----------------------------------------------
; CPM for MZ-700 with with Video Module and 80 Columns display.
IF BUILD_VERSION = 0
BUILD_VIDEOMODULE EQU 1 ; Build for the Video Module v2 board (=1) otherwise build for the 80Char Colour Board v1.0
BUILD_MZ80A EQU 0 ; Build for the Sharp MZ-80A base hardware.
BUILD_MZ700 EQU 1 ; Build for the Sharp MZ-700 base hardware.
BUILD_80C EQU 1 ; Build for an 80 column (Video Module or 40/80 Colour Card) equipped machine, 0 = standard 40 column.
ENDIF
; CPM for MZ-80A with with Video Module (if not present expects 40/80 Colour Board) and 80 Columns display.
IF BUILD_VERSION = 1
BUILD_VIDEOMODULE EQU 1 ; Build for the Video Module v2 board (=1) otherwise build for the 80Char Colour Board v1.0
BUILD_MZ80A EQU 1 ; Build for the Sharp MZ-80A base hardware.
BUILD_MZ700 EQU 0 ; Build for the Sharp MZ-700 base hardware.
BUILD_80C EQU 1 ; Build for an 80 column (Video Module or 40/80 Colour Card) equipped machine, 0 = standard 40 column.
ENDIF
; CPM for MZ-80A with with standard 40 column display.
IF BUILD_VERSION = 2
BUILD_VIDEOMODULE EQU 0 ; Build for the Video Module v2 board (=1) otherwise build for the 80Char Colour Board v1.0
BUILD_MZ80A EQU 1 ; Build for the Sharp MZ-80A base hardware.
BUILD_MZ700 EQU 0 ; Build for the Sharp MZ-700 base hardware.
BUILD_80C EQU 0 ; Build for an 80 column (Video Module or 40/80 Colour Card) equipped machine, 0 = standard 40 column.
ENDIF
;-----------------------------------------------
; Configurable settings.
;-----------------------------------------------
MAXRDRETRY EQU 002h
MAXWRRETRY EQU 002h
BLKSIZ EQU 4096 ; CP/M allocation size
HSTSIZ EQU 512 ; host disk sector size
HSTSPT EQU 32 ; host disk sectors/trk
HSTBLK EQU HSTSIZ/128 ; CP/M sects/host buff
CPMSPT EQU HSTBLK * HSTSPT ; CP/M sectors/track
SECMSK EQU HSTBLK-1 ; sector mask
WRALL EQU 0 ; write to allocated
WRDIR EQU 1 ; write to directory
WRUAL EQU 2 ; write to unallocated
TMRTICKINTV EQU 5 ; Number of 0.010mSec ticks per interrupt, ie. resolution of RTC.
MTROFFMSECS EQU 100 ; Time from last access to motor being switched off in seconds in TMRTICKINTV ticks.
IF BUILD_80C = 1
COLW EQU 80 ; Width of the display screen (ie. columns).
ELSE
COLW EQU 40 ; Width of the display screen (ie. columns).
ENDIF
ROW EQU 25 ; Number of rows on display screen.
SCRNSZ EQU COLW * ROW ; Total size, in bytes, of the screen display area.
SCRLW EQU COLW / 8 ; Number of 8 byte regions in a line for hardware scroll.
; BIOS equates
MAXDISKS EQU 7 ; Max number of Drives supported
KEYBUFSIZE EQU 64 ; Ensure this is a power of 2, max size 256.
; Debugging
ENADEBUG EQU 1 ; Enable debugging logic, 1 = enable, 0 = disable
;-----------------------------------------------
; Entry/compilation start points.
;-----------------------------------------------
MROMADDR EQU 00000H ; Start of SA1510 Monitor ROM.
CBASE EQU 0DA00H
CPMCCP EQU CBASE ; CP/M System entry
CPMBDOS EQU CPMCCP + 0806H ; BDOS entry
CPMBIOS EQU CPMCCP + 01600H ; Original CPM22 BIOS entry
CBIOSSTART EQU CPMBIOS ; Start of the actual CBIOS code.
CPMCOPYRMSG EQU CBASE+8 ; Copyright message stored in CP/M binary.
BOOT EQU CBIOSSTART + 0
WBOOT EQU CBIOSSTART + 3
WBOOTE EQU CBIOSSTART + 3
CONST EQU CBIOSSTART + 6
CONIN EQU CBIOSSTART + 9
CONOUT EQU CBIOSSTART + 12
LIST EQU CBIOSSTART + 15
PUNCH EQU CBIOSSTART + 18
READER EQU CBIOSSTART + 21
HOME EQU CBIOSSTART + 24
SELDSK EQU CBIOSSTART + 27
SETTRK EQU CBIOSSTART + 30
SETSEC EQU CBIOSSTART + 33
SETDMA EQU CBIOSSTART + 36
READ EQU CBIOSSTART + 39
WRITE EQU CBIOSSTART + 42
FRSTAT EQU CBIOSSTART + 45
SECTRN EQU CBIOSSTART + 48
QDEBUG EQU CBIOSSTART + 51
CCP EQU CBASE
CCPCLRBUF EQU CBASE + 3
IOBYT EQU 00003H ; IOBYTE address
CDISK EQU 00004H ; Address of Current drive name and user number
CPMUSERDMA EQU 00080h ; Default CPM User DMA address.
DPSIZE EQU 16 ; Size of a Disk Parameter Block
; Old Flash RAM mapping
;FDCJMP1BLK EQU 0F3C0H ; The memory mapping FlashRAM only has 64byte granularity so we need to block 64 bytes per FDC vector.
;FDCJMP1 EQU 0F3FEH ; ROM paged vector 1.
;FDCJMP2BLK EQU 0F7C0H ; The memory mapping FlashRAM only has 64byte granularity so we need to block 64 bytes per FDC vector.
;FDCJMP2 EQU 0F7FEH ; ROM paged vector 2.
; New CPLD mapping
FDCJMP1BLK EQU 0F3FEH ; The memory mapping CPLD has 1byte granularity so we need to block just 2 bytes per FDC vector.
FDCJMP1 EQU 0F3FEH ; ROM paged vector 1.
FDCJMP2BLK EQU 0F7FEH ; The memory mapping CPLD has 1byte granularity so we need to block just 2 bytes per FDC vector.
FDCJMP2 EQU 0F7FEH ; ROM paged vector 2.
;-----------------------------------------------
; Memory mapped ports in hardware.
;-----------------------------------------------
SCRN: EQU 0D000H
ARAM: EQU 0D800H
DSPCTL: EQU 0DFFFH ; Screen 40/80 select register (bit 7)
KEYPA: EQU 0E000h
KEYPB: EQU 0E001h
KEYPC: EQU 0E002h
KEYPF: EQU 0E003h
CSTR: EQU 0E002h
CSTPT: EQU 0E003h
CONT0: EQU 0E004h
CONT1: EQU 0E005h
CONT2: EQU 0E006h
CONTF: EQU 0E007h
SUNDG: EQU 0E008h
TEMP: EQU 0E008h
MEMSW: EQU 0E00CH
MEMSWR: EQU 0E010H
INVDSP: EQU 0E014H
NRMDSP: EQU 0E015H
SCLDSP: EQU 0E200H
SCLBASE: EQU 0E2H
;-----------------------------------------------
; IO ports in hardware and values.
;-----------------------------------------------
MMCFG EQU 060H ; Memory management configuration latch.
SETXMHZ EQU 062H ; Select the alternate clock frequency.
SET2MHZ EQU 064H ; Select the system 2MHz clock frequency.
CLKSELRD EQU 066H ; Read clock selected setting, 0 = 2MHz, 1 = XMHz
SVCREQ EQU 068H ; I/O Processor service request.
CPLDSTATUS EQU 06BH ; Version 2.1 CPLD status register.
CPUCFG EQU 06CH ; Version 2.2 CPU configuration register.
CPUSTATUS EQU 06CH ; Version 2.2 CPU runtime status register.
CPUINFO EQU 06DH ; Version 2.2 CPU information register.
CPLDCFG EQU 06EH ; Version 2.1 CPLD configuration register.
CPLDINFO EQU 06FH ; Version 2.1 CPLD version information register.
VMPNUM EQU 0A0H ; Set the parameter number to update.
VMPLBYTE EQU 0A1H ; Update the lower selected parameter byte.
VMPUBYTE EQU 0A2H ; Update the upper selected parameter byte.
PALSLCTOFF EQU 0A3H ; set the palette slot Off position to be adjusted.
PALSLCTON EQU 0A4H ; set the palette slot On position to be adjusted.
PALSETRED EQU 0A5H ; set the red palette value according to the PALETTE_PARAM_SEL address.
PALSETGREEN EQU 0A6H ; set the green palette value according to the PALETTE_PARAM_SEL address.
PALSETBLUE EQU 0A7H ; set the blue palette value according to the PALETTE_PARAM_SEL address.
VMPALETTE EQU 0B0H ; Select Palette:
; 0xB0 sets the palette. The Video Module supports 4 bit per colour output but there is only enough RAM for 1 bit per colour so the pallette is used to change the colours output.
; Bits [7:0] defines the pallete number. This indexes a lookup table which contains the required 4bit output per 1bit input.
; GPU:
GPUPARAM EQU 0B2H ; 0xB2 set parameters. Store parameters in a long word to be used by the graphics command processor.
; The parameter word is 128 bit and each write to the parameter word shifts left by 8 bits and adds the new byte at bits 7:0.
GPUCMD EQU 0B3H ; 0xB3 set the graphics processor unit commands.
GPUSTATUS EQU 0B3H ; [7;1] - FSM state, [0] - 1 = busy, 0 = idle
; Bits [5:0] - 0 = Reset parameters.
; 1 = Clear to val. Start Location (16 bit), End Location (16 bit), Red Filter, Green Filter, Blue Filter
;
VMCTRL EQU 0B8H ; Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
VMGRMODE EQU 0B9H ; Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
VMREDMASK EQU 0BAH ; Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMGREENMASK EQU 0BBH ; Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMBLUEMASK EQU 0BCH ; Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMPAGE EQU 0BDH ; Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
VMVGATTR EQU 0BEH ; Select VGA Border colour and attributes. Bit 2 = Red, 1 = Green, 0 = Blue.
VMVGAMODE EQU 0BFH ; Select VGA output mode. Bits [3:0] - Output mode.
GDCRTC EQU 0CFH ; MZ-800 CRTC control register
GDCMD EQU 0CEH ; MZ-800 CRTC Mode register
GDGRF EQU 0CDH ; MZ-800 read format register
GDGWF EQU 0CCH ; MZ-800 write format register
MMIO0 EQU 0E0H ; MZ-700/MZ-800 Memory Management Set 0
MMIO1 EQU 0E1H ; MZ-700/MZ-800 Memory Management Set 1
MMIO2 EQU 0E2H ; MZ-700/MZ-800 Memory Management Set 2
MMIO3 EQU 0E3H ; MZ-700/MZ-800 Memory Management Set 3
MMIO4 EQU 0E4H ; MZ-700/MZ-800 Memory Management Set 4
MMIO5 EQU 0E5H ; MZ-700/MZ-800 Memory Management Set 5
MMIO6 EQU 0E6H ; MZ-700/MZ-800 Memory Management Set 6
MMIO7 EQU 0E7H ; MZ-700/MZ-800 Memory Management Set 7
SYSCTRL EQU 0F0H ; System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
GRAMMODE EQU 0F4H ; MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
;-----------------------------------------------
; IO Registers
;-----------------------------------------------
FDC EQU 0D8h ; MB8866 IO Region 0D8h - 0DBh
FDC_CR EQU FDC + 000h ; Command Register
FDC_STR EQU FDC + 000h ; Status Register
FDC_TR EQU FDC + 001h ; Track Register
FDC_SCR EQU FDC + 002h ; Sector Register
FDC_DR EQU FDC + 003h ; Data Register
FDC_MOTOR EQU FDC + 004h ; DS[0-3] and Motor control. 4 drives DS= BIT 0 -> Bit 2 = Drive number, 2=1,1=0,0=0 DS0, 2=1,1=0,0=1 DS1 etc
; bit 7 = 1 MOTOR ON LOW (Active)
FDC_SIDE EQU FDC + 005h ; Side select, Bit 0 when set = SIDE SELECT LOW
;-----------------------------------------------
; Common character definitions.
;-----------------------------------------------
SCROLL EQU 001H ;Set scroll direction UP.
BELL EQU 007H
SPACE EQU 020H
TAB EQU 009H ;TAB ACROSS (8 SPACES FOR SD-BOARD)
CR EQU 00DH
LF EQU 00AH
FF EQU 00CH
CS EQU 0CH ; Clear screen
DELETE EQU 07FH
BACKS EQU 008H
SOH EQU 1 ; For XModem etc.
EOT EQU 4
ACK EQU 6
NAK EQU 015H
NUL EQU 000H
NULL EQU 000H
CTRL_A EQU 001H
CTRL_B EQU 002H
CTRL_C EQU 003H
CTRL_D EQU 004H
CTRL_E EQU 005H
CTRL_F EQU 006H
CTRL_G EQU 007H
CTRL_H EQU 008H
CTRL_I EQU 009H
CTRL_J EQU 00AH
CTRL_K EQU 00BH
CTRL_L EQU 00CH
CTRL_M EQU 00DH
CTRL_N EQU 00EH
CTRL_O EQU 00FH
CTRL_P EQU 010H
CTRL_Q EQU 011H
CTRL_R EQU 012H
CTRL_S EQU 013H
CTRL_T EQU 014H
CTRL_U EQU 015H
CTRL_V EQU 016H
CTRL_W EQU 017H
CTRL_X EQU 018H
CTRL_Y EQU 019H
CTRL_Z EQU 01AH
ESC EQU 01BH
CTRL_SLASH EQU 01CH
CTRL_LB EQU 01BH
CTRL_RB EQU 01DH
CTRL_CAPPA EQU 01EH
CTRL_UNDSCR EQU 01FH
CTRL_AT EQU 000H
NOKEY EQU 0F0H
CURSRIGHT EQU 0F1H
CURSLEFT EQU 0F2H
CURSUP EQU 0F3H
CURSDOWN EQU 0F4H
DBLZERO EQU 0F5H
INSERT EQU 0F6H
CLRKEY EQU 0F7H
HOMEKEY EQU 0F8H
BREAKKEY EQU 0FBH
GRAPHKEY EQU 0FCH
ALPHAKEY EQU 0FDH
; MMC/SD command (SPI mode)
CMD0 EQU 64 + 0 ; GO_IDLE_STATE
CMD1 EQU 64 + 1 ; SEND_OP_COND
ACMD41 EQU 0x40+41 ; SEND_OP_COND (SDC)
CMD8 EQU 64 + 8 ; SEND_IF_COND
CMD9 EQU 64 + 9 ; SEND_CSD
CMD10 EQU 64 + 10 ; SEND_CID
CMD12 EQU 64 + 12 ; STOP_TRANSMISSION
CMD13 EQU 64 + 13 ; SEND_STATUS
ACMD13 EQU 0x40+13 ; SD_STATUS (SDC)
CMD16 EQU 64 + 16 ; SET_BLOCKLEN
CMD17 EQU 64 + 17 ; READ_SINGLE_BLOCK
CMD18 EQU 64 + 18 ; READ_MULTIPLE_BLOCK
CMD23 EQU 64 + 23 ; SET_BLOCK_COUNT
ACMD23 EQU 0x40+23 ; SET_WR_BLK_ERASE_COUNT (SDC)
CMD24 EQU 64 + 24 ; WRITE_BLOCK
CMD25 EQU 64 + 25 ; WRITE_MULTIPLE_BLOCK
CMD32 EQU 64 + 32 ; ERASE_ER_BLK_START
CMD33 EQU 64 + 33 ; ERASE_ER_BLK_END
CMD38 EQU 64 + 38 ; ERASE
CMD55 EQU 64 + 55 ; APP_CMD
CMD58 EQU 64 + 58 ; READ_OCR
SD_SECSIZE EQU 512 ; Default size of an SD Sector
SD_RETRIES EQU 00100H ; Number of retries before giving up.
; Card type flags (CardType)
CT_MMC EQU 001H ; MMC ver 3
CT_SD1 EQU 002H ; SD ver 1
CT_SD2 EQU 004H ; SD ver 2
CT_SDC EQU CT_SD1|CT_SD2 ; SD
CT_BLOCK EQU 008H ; Block addressing
; Disk types.
DSKTYP_FDC EQU 0 ; Type of disk is a Floppy disk and handled by the FDC controller.
;DSKTYP_ROM EQU 1 ; Type of disk is a ROM and handled by the ROM methods.
DSKTYP_SDC EQU 2 ; Type of disk is an SD Card and handled by the SD Card methods.
DSKTYP_RAM EQU 3 ; Type of disk is a RAM Drive handled by ROM/RAM methods.
;
;-----------------------------------------------
; CPLD Configuration constants.
;-----------------------------------------------
MODE_MZ80K EQU 0 ; Set to MZ-80K mode.
MODE_MZ80C EQU 1 ; Set to MZ-80C mode.
MODE_MZ1200 EQU 2 ; Set to MZ-1200 mode.
MODE_MZ80A EQU 3 ; Set to MZ-80A mode (base mode on MZ-80A hardware).
MODE_MZ700 EQU 4 ; Set to MZ-700 mode (base mode on MZ-700 hardware).
MODE_MZ800 EQU 5 ; Set to MZ-800 mode.
MODE_MZ80B EQU 6 ; Set to MZ-80B mode.
MODE_MZ2000 EQU 7 ; Set to MZ-2000 mode.
MODE_VIDEO_FPGA EQU 8 ; Bit flag (bit 3) to switch CPLD into using the new FPGA video hardware.
MODE_RESET_PRESERVE EQU 080H ; Preserve register configuration through reset.
;-----------------------------------------------
; CPLD Command Instruction constants.
;-----------------------------------------------
CPLD_RESET_HOST EQU 1 ; CPLD level command to reset the host system.
CPLD_HOLD_HOST_BUS EQU 2 ; CPLD command to hold the host bus.
CPLD_RELEASE_HOST_BUS EQU 3 ; CPLD command to release the host bus.
;-----------------------------------------------
; FPGA CPU enhancement control bits.
;-----------------------------------------------
CPUMODE_SET_Z80 EQU 000H ; Set the CPU to the hard Z80.
CPUMODE_SET_T80 EQU 001H ; Set the CPU to the soft T80.
CPUMODE_SET_ZPU_EVO EQU 002H ; Set the CPU to the soft ZPU Evolution.
CPUMODE_SET_AAA EQU 004H ; Place holder for a future soft CPU.
CPUMODE_SET_BBB EQU 008H ; Place holder for a future soft CPU.
CPUMODE_SET_CCC EQU 010H ; Place holder for a future soft CPU.
CPUMODE_SET_DDD EQU 020H ; Place holder for a future soft CPU.
CPUMODE_IS_Z80 EQU 000H ; Status value to indicate if the hard Z80 available.
CPUMODE_IS_T80 EQU 001H ; Status value to indicate if the soft T80 available.
CPUMODE_IS_ZPU_EVO EQU 002H ; Status value to indicate if the soft ZPU Evolution available.
CPUMODE_IS_AAA EQU 004H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_BBB EQU 008H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_CCC EQU 010H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_DDD EQU 020H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_RESET_CPU EQU 080H ; Reset the soft CPU. Active high, when high the CPU is held in RESET, when low the CPU runs.
CPUMODE_IS_SOFT_AVAIL EQU 040H ; Marker to indicate if the underlying FPGA can support soft CPU's.
CPUMODE_IS_SOFT_MASK EQU 0C0H ; Mask to filter out the Soft CPU availability flags.
CPUMODE_IS_CPU_MASK EQU 03FH ; Mask to filter out which soft CPU's are available.
;-----------------------------------------------
; Video Module control bits.
;-----------------------------------------------
MODE_80CHAR EQU 010H ; Enable 80 character display.
MODE_COLOUR EQU 020H ; Enable colour display.
SYSMODE_MZ80A EQU 000H ; System board mode MZ80A, 2MHz CPU/Bus.
SYSMODE_MZ80B EQU 020H ; System board mode MZ80B, 4MHz CPU/Bus.
SYSMODE_MZ2000 EQU 020H ; System board mode MZ2000, 4MHz CPU/Bus.
SYSMODE_MZ700 EQU 042H ; System board mode MZ700, 3.54MHz CPU/Bus.
VMMODE_MZ80K EQU 000H ; Video mode = MZ80K
VMMODE_MZ80C EQU 001H ; Video mode = MZ80C
VMMODE_MZ1200 EQU 002H ; Video mode = MZ1200
VMMODE_MZ80A EQU 003H ; Video mode = MZ80A
VMMODE_MZ700 EQU 004H ; Video mode = MZ700
VMMODE_MZ800 EQU 005H ; Video mode = MZ800
VMMODE_MZ1500 EQU 006H ; Video mode = MZ1500
VMMODE_MZ80B EQU 007H ; Video mode = MZ80B
VMMODE_MZ2000 EQU 008H ; Video mode = MZ2000
VMMODE_MZ2200 EQU 009H ; Video mode = MZ2200
VMMODE_MZ2500 EQU 00AH ; Video mode = MZ2500
VMMODE_PCGRAM EQU 020H ; Enable PCG RAM.
VMMODE_VGA_OFF EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT50 EQU 001H ; Set VGA mode off, external monitor is driven by standard internal 50Hz signals.
VMMODE_VGA_640x480 EQU 002H ; Set external monitor to VGA 640x480 @ 60Hz mode.
VMMODE_VGA_800x600 EQU 003H ; Set external monitor to VGA 800x600 @ 60Hz mode.
;-----------------------------------------------
; GPU commands.
;-----------------------------------------------
GPUCLEARVRAM EQU 001H ; Clear the VRAM without updating attributes.
GPUCLEARVRAMCA EQU 002H ; Clear the VRAM/ARAM with given attribute byte,
GPUCLEARVRAMP EQU 003H ; Clear the VRAM/ARAM with parameters.
GPUCLEARGRAM EQU 081H ; Clear the entire Framebuffer.
GPUCLEARGRAMP EQU 082H ; Clear the Framebuffer according to parameters.
GPURESET EQU 0FFH ; Reset the GPU, return to idle state.
;-----------------------------------------------
; tranZPUter SW Memory Management modes
;-----------------------------------------------
TZMM_ENIOWAIT EQU 020H ; Memory management IO Wait State enable - insert a wait state when an IO operation to E0-FF is executed.
TZMM_ORIG EQU 000H ; Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
TZMM_BOOT EQU 001H ; Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
TZMM_TZFS EQU 002H ; TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
TZMM_TZFS2 EQU 003H ; TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
TZMM_TZFS3 EQU 004H ; TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
TZMM_TZFS4 EQU 005H ; TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
TZMM_CPM EQU 006H ; TZMM_ENIOWAIT ; 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.
TZMM_CPM2 EQU 007H ; TZMM_ENIOWAIT ; 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.
TZMM_COMPAT EQU 008H ; TZMM_ENIOWAIT ; Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
TZMM_HOSTACCESS EQU 009H ; TZMM_ENIOWAIT ; Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
TZMM_MZ700_0 EQU 00AH ; TZMM_ENIOWAIT ; 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.
TZMM_MZ700_1 EQU 00BH ; TZMM_ENIOWAIT ; 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.
TZMM_MZ700_2 EQU 00CH ; TZMM_ENIOWAIT ; 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.
TZMM_MZ700_3 EQU 00DH ; TZMM_ENIOWAIT ; 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.
TZMM_MZ700_4 EQU 00EH ; TZMM_ENIOWAIT ; 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.
TZMM_MZ800 EQU 00FH ; TZMM_ENIOWAIT ; MZ800 Mode - Tracks original hardware mode offering MZ700/MZ800 configurations.
TZMM_MZ2000 EQU 010H + TZMM_ENIOWAIT; ; MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
TZMM_FPGA EQU 015H ; TZMM_ENIOWAIT ; Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
TZMM_TZPUM EQU 016H ; TZMM_ENIOWAIT ; Everything in on mainboard, no access to tranZPUter memory.
TZMM_TZPU EQU 017H ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU0 EQU 018H ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU1 EQU 019H ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
;TZMM_TZPU2 EQU 01AH ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
;TZMM_TZPU3 EQU 01BH ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
;TZMM_TZPU4 EQU 01CH ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
;TZMM_TZPU5 EQU 01DH ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
;TZMM_TZPU6 EQU 01EH ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
;TZMM_TZPU7 EQU 01FH ; TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
;-----------------------------------------------
; TZ File System Header (MZF)
;-----------------------------------------------
TZFS_ATRB: EQU 00000h ; Code Type, 01 = Machine Code.
TZFS_NAME: EQU 00001h ; Title/Name (17 bytes).
TZFS_SIZE: EQU 00012h ; Size of program.
TZFS_DTADR: EQU 00014h ; Load address of program.
TZFS_EXADR: EQU 00016h ; Exec address of program.
TZFS_COMNT: EQU 00018h ; Comment
TZFS_MZFLEN: EQU 128 ; Length of the MZF header.
TZFS_CMTLEN: EQU 104 ; Length of the comment field
;
; CPM constants
;
CPM_SD_SEC EQU 32
CPM_SD_TRK EQU 1024
CPM_SD_IMGSZ EQU CPM_SD_TRK * CPM_SD_SEC * SD_SECSIZE
;-----------------------------------------------
; BIOS WORK AREA (MZ80A)
;-----------------------------------------------
TZVARMEM: EQU 0F4A0H
TZSVCMEM: EQU 0F560H ; Start of a memory structure used to communicate with the K64F I/O processor for services such as disk access.
TZSVCSIZE: EQU 00280H ;
TZSVCDIRSZ: EQU 20 ; Size of the directory/file name.
TZSVCFILESZ: EQU 17 ; Size of a Sharp filename.
TZSVCLONGFILESZ: EQU 31 ; Size of a standard filename.
TZSVCLONGFMTSZ: EQU 20 ; Size of a formatted standard filename for use in directory listings.
TZSVCWILDSZ: EQU 20 ; Size of the wildcard.
TZSVCSECSIZE: EQU 512
TZSVCDIR_ENTSZ: EQU 32 ; Size of a directory entry.
TZSVCWAITIORETRIES: EQU 500 ; Wait retries for IO response.
TZSVCWAITCOUNT: EQU 65535 ; Wait retries for IO request response.
TZSVC_FTYPE_MZF: EQU 0 ; File type being handled is an MZF
TZSVC_FTYPE_MZFHDR: EQU 1 ; File type being handled is an MZF Header.
TZSVC_FTYPE_CAS: EQU 2 ; File type being handled is an CASsette BASIC script.
TZSVC_FTYPE_BAS: EQU 3 ; File type being handled is an BASic script
TZSVC_FTYPE_ALL: EQU 10 ; Handle any filetype.
TZSVC_FTYPE_ALLFMT: EQU 11 ; Special case for directory listings, all files but truncated and formatted.
TZSVC_CMD_READDIR EQU 01H ; Service command to open a directory and return the first block of entries.
TZSVC_CMD_NEXTDIR EQU 02H ; Service command to return the next block of an open directory.
TZSVC_CMD_READFILE EQU 03H ; Service command to open a file and return the first block.
TZSVC_CMD_NEXTREADFILE EQU 04H ; Service command to return the next block of an open file.
TZSVC_CMD_WRITEFILE EQU 05H ; Service command to create a file and save the first block.
TZSVC_CMD_NEXTWRITEFILE EQU 06H ; Service command to write the next block to the open file.
TZSVC_CMD_CLOSE EQU 07H ; Service command to close any open file or directory.
TZSVC_CMD_LOADFILE EQU 08H ; Service command to load a file directly into tranZPUter memory.
TZSVC_CMD_SAVEFILE EQU 09H ; Service command to save a file directly from tranZPUter memory.
TZSVC_CMD_ERASEFILE EQU 0aH ; Service command to erase a file on the SD card.
TZSVC_CMD_CHANGEDIR EQU 0bH ; Service command to change the active directory on the SD card.
TZSVC_CMD_LOAD40ABIOS EQU 20H ; Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD80ABIOS EQU 21H ; Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD700BIOS40 EQU 22H ; Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
TZSVC_CMD_LOAD700BIOS80 EQU 23H ; Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
TZSVC_CMD_LOAD80BIPL EQU 24H ; Service command requesting the MZ-80B IPL is loaded.
TZSVC_CMD_LOAD800BIOS EQU 25H ; Service command requesting that the MZ800 9Z-504M BIOS is loaded.
TZSVC_CMD_LOAD2000IPL EQU 26H ; Service command requesting the MZ-2000 IPL is loaded.
TZSVC_CMD_LOADTZFS EQU 2FH ; Service command requesting the loading of TZFS. This service is for machines which normally dont have a monitor BIOS. ie. MZ-80B/MZ-2000 and manually request TZFS.
TZSVC_CMD_LOADBDOS EQU 30H ; Service command to reload CPM BDOS+CCP.
TZSVC_CMD_ADDSDDRIVE EQU 31H ; Service command to attach a CPM disk to a drive number.
TZSVC_CMD_READSDDRIVE EQU 32H ; Service command to read an attached SD file as a CPM disk drive.
TZSVC_CMD_WRITESDDRIVE EQU 33H ; Service command to write to a CPM disk drive which is an attached SD file.
TZSVC_CMD_CPU_BASEFREQ EQU 40H ; Service command to switch to the mainboard frequency.
TZSVC_CMD_CPU_ALTFREQ EQU 41H ; Service command to switch to the alternate frequency provided by the K64F.
TZSVC_CMD_CPU_CHGFREQ EQU 42H ; Service command to set the alternate frequency in hertz.
TZSVC_CMD_CPU_SETZ80 EQU 50H ; Service command to switch to the external Z80 hard cpu.
TZSVC_CMD_CPU_SETT80 EQU 51H ; Service command to switch to the internal T80 soft cpu.
TZSVC_CMD_CPU_SETZPUEVO EQU 52H ; Service command to switch to the internal ZPU Evolution soft cpu.
TZSVC_CMD_EMU_SETMZ80K EQU 53H ; Service command to switch to the internal Sharp MZ Series Emulation of the MZ80K.
TZSVC_CMD_EMU_SETMZ80C EQU 54H ; "" "" "" MZ80C.
TZSVC_CMD_EMU_SETMZ1200 EQU 55H ; "" "" "" MZ1200.
TZSVC_CMD_EMU_SETMZ80A EQU 56H ; "" "" "" MZ80A.
TZSVC_CMD_EMU_SETMZ700 EQU 57H ; "" "" "" MZ700.
TZSVC_CMD_EMU_SETMZ800 EQU 58H ; "" "" "" MZ800.
TZSVC_CMD_EMU_SETMZ1500 EQU 59H ; "" "" "" MZ1500.
TZSVC_CMD_EMU_SETMZ80B EQU 5AH ; "" "" "" MZ80B.
TZSVC_CMD_EMU_SETMZ2000 EQU 5BH ; "" "" "" MZ2000.
TZSVC_CMD_EMU_SETMZ2200 EQU 5CH ; "" "" "" MZ2200.
TZSVC_CMD_EMU_SETMZ2500 EQU 5DH ; "" "" "" MZ2500.
TZSVC_CMD_EXIT EQU 07FH ; Service command to terminate TZFS and restart the machine in original mode.
TZSVC_STATUS_OK EQU 000H ; Flag to indicate the K64F processing completed successfully.
TZSVC_STATUS_REQUEST EQU 0FEH ; Flag to indicate the Z80 has made a request to the K64F.
TZSVC_STATUS_PROCESSING EQU 0FFH ; Flag to indicate the K64F is processing a command.

View File

@@ -0,0 +1,152 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: Macros.asm
;- Created: July 2019
;- Author(s): Philip Smart
;- Description: Z80 Assembler Macros Library
;- This is an aassembly language macro source file containing resusable code in the form
; of Macros for the various Z80 projects under development.
;- Credits:
;- Copyright: (c) 2018-2020 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
; the following is only to get the original length of 2048 bytes
ALIGN: MACRO ?boundary
DS ?boundary - 1 - ($ + ?boundary - 1) % ?boundary, 0FFh
ENDM
; the following is only to get the original length of 2048 bytes
ALIGN_NOPS: MACRO ?boundary
DS ?boundary - 1 - ($ + ?boundary - 1) % ?boundary, 000h
ENDM
;
; Pads up to a certain address.
; Gives an error message if that address is already exceeded.
;
PAD: MACRO ?address
IF $ > ?address
ERROR "Alignment exceeds %s"; % ?address
ENDIF
DS ?address - $
ENDM
;
; Pads up to the next multiple of the specified address.
;
;ALIGN: MACRO ?boundary
; ds ?boundary - 1 - ($ + ?boundary - 1) % ?boundary
; ENDM
;
; Pads to ensure a section of the given size does not cross a 100H boundary.
;
ALIGN_FIT8: MACRO ?size
DS (($ + ?size - 1) >> 8) != ($ >> 8) && (100H - ($ & 0FFH)) || 0
ENDM
; Macro to create a Jump table entry point for a Bank to Bank function call.
; The address of the real function in the required page is given as ?addr
; and the bank in which it will reside is given in ?bank. The logic then takes
; care of stack and memory mode manipulation to call the method and return to the
; caller with all registers unaffected going to the called function and returning from
; the called function. This allows any method to be placed in a bank as space dictates.
CALLBNK: MACRO ?addr, ?bank
EXX
EX AF,AF'
LD HL,?addr ; Real function to call.
LD A,?bank ; Bank in which the function resides.
JP BANKTOBANK_
ENDM
; As above but just jump to the required location in the alternate bank, no return.
JMPBNK: MACRO ?addr, ?bank
EX AF,AF'
LD A,?bank ; Bank in which the function resides.
LD (MMCFGVAL),A ; Store the value in a memory variable as we cant read the latch once programmed.
OUT (MMCFG),A ; Switch to the TZFS memory mode, SA1510 is now in RAM at 0000H
EX AF,AF'
LD HL,?addr ; Real function to jump to.
JP (HL)
ENDM
; Method to allow one bank to call a routine in another bank with all registers preserved in and out and
; reentrant so banks can call banks. It is costly in processing time and should only be
; used infrequently.
;
; Input: A = Memory mode to switch into.
; (HLSAVE)= Original HL to pass to caller.
; HL = Address to call.
; AF = Stored on stack to pass to called function.
; All other registers passed to called function.
; All registers are passed untouched to the caller.
; Stack; BKTOBKRET:AF (original memory mode) : Caller return address.
; Output: All registers and flags returned to caller.
;
JMPTOBNK: MACRO
LD (FNADDR),HL ; Save the function to call address stored in HL
LD L,A ; Save A to retrieve the old Memory mode and push it on the stack so it can be restored after return.
LD A,(MMCFGVAL)
PUSH AF
LD A,L
; NB. Dont disable interrupts, goes to mode 7 then returns to MMCFGVAL,so apart from a double switch there should be no race state.
LD (MMCFGVAL),A ; Store the value in a memory variable as we cant read the latch once programmed.
OUT (MMCFG),A ; Switch to the TZFS memory mode, SA1510 is now in RAM at 0000H
LD HL,BKTOBKRET ; Store the return address which must come back to this functionality before original caller.
PUSH HL
LD HL,(FNADDR) ; Push the address of the function to call onto the stack.
PUSH HL
EXX
EX AF,AF'
RET ; Call the required function by popping address off stack.
BKTOBKRET: EX (SP),HL ; Retrieve original memory mode from stack.
EX AF,AF'
LD A,H
LD (MMCFGVAL),A ; Store the value in a memory variable as we cant read the latch once programmed.
OUT (MMCFG),A ; Switch to the TZFS memory mode, SA1510 is now in RAM at 0000H
EX AF,AF'
POP HL ; Restore HL.
RET
ENDM
; Alternate version which preserves caller stack and creates local stack, used in CPM where the caller (CPM) has a tiny stack
; and the CBIOS needs more space. This version isnt reentrant, it is only used one way, CPM -> CBIOS.
JMPTOBNK2: MACRO
LD (STKSAVE),SP
LD SP,CBIOSSTACK
LD (FNADDR),HL ; Save the function to call address stored in HL
; NB. Dont disable interrupts, goes to mode 7 then returns to MMCFGVAL,so apart from a double switch there should be no race state.
LD A,TZMM_CPM2
LD (MMCFGVAL),A ; Store the value in a memory variable as we cant read the latch once programmed.
OUT (MMCFG),A ; Switch to the TZFS memory mode, SA1510 is now in RAM at 0000H
LD HL,BKTOBKRET2 ; Store the return address which must come back to this functionality before original caller.
PUSH HL
LD HL,(FNADDR) ; Push the address of the function to call onto the stack.
PUSH HL
EXX
EX AF,AF'
RET ; Call the required function by popping address off stack.
BKTOBKRET2: EX AF,AF'
LD A,TZMM_CPM
LD (MMCFGVAL),A ; Store the value in a memory variable as we cant read the latch once programmed.
OUT (MMCFG),A ; Switch to the TZFS memory mode, SA1510 is now in RAM at 0000H
EX AF,AF'
LD SP,(STKSAVE)
RET
ENDM

View File

@@ -0,0 +1 @@
BUILD_VERSION EQU 3

View File

@@ -0,0 +1,534 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: MSBASIC_Definitions.asm
;- Created: June 2020
;- Author(s): Philip Smart
;- Description: Sharp MZ series CPM v2.23
;- Definitions for the Sharp MZ80A CPM v2.23 OS used in the RFS
;-
;- Credits:
;- Copyright: (c) 2019-20 Philip Smart <philip.smart@net2net.org>
;-
;- History: Jan 2020 - Initial version.
; May 2020 - Advent of the new RFS PCB v2.0, quite a few changes to accommodate the
; additional and different hardware. The SPI is now onboard the PCB and
; not using the printer interface card.
; Jun 2020 - Copied and strpped from TZFS for BASIC.
; Mar 2021 - Updates to backport changes from the RFS version after v2.1 hw changes.
;
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;-----------------------------------------------
; Features.
;-----------------------------------------------
;-----------------------------------------------
;-----------------------------------------------
; Configurable settings.
;-----------------------------------------------
; Build options. Set just one to '1' the rest to '0'.
; NB: As there are now 4 versions and 1 or more need to be built, ie. MZ-80A and RFS version for RFS, a flag is set in the file
; BASIC_build.asm which configures the equates below for the correct build.
; MZ-80A Standard Machine Configuration.
IF BUILD_VERSION = 0
BUILD_MZ80A EQU 1 ; Build for the standard Sharp MZ80A, no lower memory. Manually change MAXMEM above.
BUILD_MZ700 EQU 0 ; Build for the Sharp MZ-700 base hardware.
BUILD_MZ80A_TZFS EQU 0 ; Build for TZFS running on an MZ-80A where extended memory is available.
BUILD_MZ700_TZFS EQU 0 ; Build for TZFS running on an MZ-700 where extended memory is available.
BUILD_VIDEOMODULE EQU 0 ; Build for the Video Module v2 board (=1) otherwise build for the 80Char Colour Board v1.0
BUILD_80C EQU 0
INCLUDE_ANSITERM EQU 1 ; Include the Ansi terminal emulation processor in the build.
ENDIF
; MZ-700 Standard Machine Configuration.
IF BUILD_VERSION = 1
BUILD_MZ80A EQU 0
BUILD_MZ700 EQU 1 ; Build for the Sharp MZ-700 base hardware.
BUILD_MZ80A_TZFS EQU 0 ; Build for TZFS running on an MZ-80A where extended memory is available.
BUILD_MZ700_TZFS EQU 0 ; Build for TZFS running on an MZ-700 where extended memory is available.
BUILD_VIDEOMODULE EQU 0 ; Build for the Video Module v2 board (=1) otherwise build for the 80Char Colour Board v1.0
BUILD_80C EQU 0
INCLUDE_ANSITERM EQU 1 ; Include the Ansi terminal emulation processor in the build.
ENDIF
; TZFS Enhanced MZ-80A/MZ-700 with no video card upgrade.
IF BUILD_VERSION = 2
BUILD_MZ80A EQU 0
BUILD_MZ700 EQU 0 ; Build for the Sharp MZ-700 base hardware.
BUILD_MZ80A_TZFS EQU 0 ; Build for TZFS running on an MZ-80A where extended memory is available.
BUILD_MZ700_TZFS EQU 1 ; Build for TZFS running on an MZ-700 where extended memory is available.
BUILD_VIDEOMODULE EQU 0 ; Build for the Video Module v2 board (=1) otherwise build for the 80Char Colour Board v1.0
BUILD_80C EQU 0
INCLUDE_ANSITERM EQU 1 ; Include the Ansi terminal emulation processor in the build.
ENDIF
; TZFS Enhanced MZ-80A/MZ-700 with VideoModule (or 40/80 Colour Board on MZ-80A).
IF BUILD_VERSION = 3
BUILD_MZ700 EQU 0 ; Build for the Sharp MZ-700 base hardware.
BUILD_MZ80A EQU 0
BUILD_MZ80A_TZFS EQU 0 ; Build for TZFS running on an MZ-80A where extended memory is available.
BUILD_MZ700_TZFS EQU 1 ; Build for TZFS running on an MZ-700 where extended memory is available.
BUILD_VIDEOMODULE EQU 1 ; Build for the Video Module v2 board (=1) otherwise build for the 80Char Colour Board v1.0
BUILD_80C EQU 1
INCLUDE_ANSITERM EQU 1 ; Include the Ansi terminal emulation processor in the build.
ENDIF
IF BUILD_80C = 1
COLW: EQU 80 ; Width of the display screen (ie. columns).
ELSE
COLW: EQU 40 ; Width of the display screen (ie. columns).
ENDIF
TMRTICKINTV EQU 5 ; Number of 0.010mSec ticks per interrupt, ie. resolution of RTC.
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
SCRLW: EQU COLW / 8 ; Number of 8 byte regions in a line for hardware scroll.
; BIOS equates
KEYBUFSIZE EQU 64 ; Ensure this is a power of 2, max size 256.
IF BUILD_MZ80A = 1
MAXMEM EQU 0CFFFH ; Top of RAM on a standard Sharp MZ80A.
ELSE
MAXMEM EQU 10000H - TZSVCSIZE ; Top of RAM on the tranZPUter
ENDIF
; Tape load/save modes. Used as a flag to enable common code.
TAPELOAD EQU 1
CTAPELOAD EQU 2
TAPESAVE EQU 3
CTAPESAVE EQU 4
; Debugging
ENADEBUG EQU 0 ; Enable debugging logic, 1 = enable, 0 = disable
;-----------------------------------------------
; CMT Object types.
;-----------------------------------------------
ATR_OBJ EQU 1
ATR_BASIC_PROG EQU 2
ATR_BASIC_DATA EQU 3
ATR_SRC_FILE EQU 4
ATR_RELOC_FILE EQU 5
ATR_BASIC_MSCAS EQU 07EH
ATR_BASIC_MSTXT EQU 07FH
ATR_PASCAL_PROG EQU 0A0H
ATR_PASCAL_DATA EQU 0A1H
CMTATRB EQU 010F0H
CMTNAME EQU 010F1H
;-------------------------------------------------------
; Function entry points in the standard SA-1510 Monitor.
;-------------------------------------------------------
QWRI EQU 00021h
QWRD EQU 00024h
QRDI EQU 00027h
QRDD EQU 0002Ah
QVRFY EQU 0002Dh
;-----------------------------------------------
; BASIC ERROR CODE VALUES
;-----------------------------------------------
NF EQU 00H ; NEXT without FOR
SN EQU 02H ; Syntax error
RG EQU 04H ; RETURN without GOSUB
OD EQU 06H ; Out of DATA
FC EQU 08H ; Function call error
OV EQU 0AH ; Overflow
OM EQU 0CH ; Out of memory
UL EQU 0EH ; Undefined line number
BS EQU 10H ; Bad subscript
DDA EQU 12H ; Re-DIMensioned array
DZ EQU 14H ; Division by zero (/0)
ID EQU 16H ; Illegal direct
TM EQU 18H ; Type miss-match
OS EQU 1AH ; Out of string space
LS EQU 1CH ; String too long
ST EQU 1EH ; String formula too complex
CN EQU 20H ; Can't CONTinue
UF EQU 22H ; UnDEFined FN function
MO EQU 24H ; Missing operand
HX EQU 26H ; HEX error
BN EQU 28H ; BIN error
BV EQU 2AH ; Bad Value error
IO EQU 2CH ; IO error
;-----------------------------------------------
; Memory mapped ports in hardware.
;-----------------------------------------------
SCRN: EQU 0D000H
ARAM: EQU 0D800H
DSPCTL: EQU 0DFFFH ; Screen 40/80 select register (bit 7)
KEYPA: EQU 0E000h
KEYPB: EQU 0E001h
KEYPC: EQU 0E002h
KEYPF: EQU 0E003h
CSTR: EQU 0E002h
CSTPT: EQU 0E003h
CONT0: EQU 0E004h
CONT1: EQU 0E005h
CONT2: EQU 0E006h
CONTF: EQU 0E007h
SUNDG: EQU 0E008h
TEMP: EQU 0E008h
MEMSW: EQU 0E00CH
MEMSWR: EQU 0E010H
INVDSP: EQU 0E014H
NRMDSP: EQU 0E015H
SCLDSP: EQU 0E200H
SCLBASE: EQU 0E2H
;-----------------------------------------------
; IO Registers
;-----------------------------------------------
FDC EQU 0D8h ; MB8866 IO Region 0D8h - 0DBh
FDC_CR EQU FDC + 000h ; Command Register
FDC_STR EQU FDC + 000h ; Status Register
FDC_TR EQU FDC + 001h ; Track Register
FDC_SCR EQU FDC + 002h ; Sector Register
FDC_DR EQU FDC + 003h ; Data Register
FDC_MOTOR EQU FDC + 004h ; DS[0-3] and Motor control. 4 drives DS= BIT 0 -> Bit 2 = Drive number, 2=1,1=0,0=0 DS0, 2=1,1=0,0=1 DS1 etc
; bit 7 = 1 MOTOR ON LOW (Active)
FDC_SIDE EQU FDC + 005h ; Side select, Bit 0 when set = SIDE SELECT LOW
;-----------------------------------------------
; Common character definitions.
;-----------------------------------------------
SCROLL EQU 001H ;Set scroll direction UP.
BELL EQU 007H
SPACE EQU 020H
TAB EQU 009H ;TAB ACROSS (8 SPACES FOR SD-BOARD)
CR EQU 00DH
LF EQU 00AH
FF EQU 00CH
CS EQU 0CH ; Clear screen
DELETE EQU 07FH
BACKS EQU 008H
SOH EQU 1 ; For XModem etc.
EOT EQU 4
ACK EQU 6
NAK EQU 015H
NUL EQU 000H
;NULL EQU 000H
CTRL_A EQU 001H
CTRL_B EQU 002H
CTRL_C EQU 003H
CTRL_D EQU 004H
CTRL_E EQU 005H
CTRL_F EQU 006H
CTRL_G EQU 007H
CTRL_H EQU 008H
CTRL_I EQU 009H
CTRL_J EQU 00AH
CTRL_K EQU 00BH
CTRL_L EQU 00CH
CTRL_M EQU 00DH
CTRL_N EQU 00EH
CTRL_O EQU 00FH
CTRL_P EQU 010H
CTRL_Q EQU 011H
CTRL_R EQU 012H
CTRL_S EQU 013H
CTRL_T EQU 014H
CTRL_U EQU 015H
CTRL_V EQU 016H
CTRL_W EQU 017H
CTRL_X EQU 018H
CTRL_Y EQU 019H
CTRL_Z EQU 01AH
ESC EQU 01BH
CTRL_SLASH EQU 01CH
CTRL_LB EQU 01BH
CTRL_RB EQU 01DH
CTRL_CAPPA EQU 01EH
CTRL_UNDSCR EQU 01FH
CTRL_AT EQU 000H
NOKEY EQU 0F0H
CURSRIGHT EQU 0F1H
CURSLEFT EQU 0F2H
CURSUP EQU 0F3H
CURSDOWN EQU 0F4H
DBLZERO EQU 0F5H
INSERT EQU 0F6H
CLRKEY EQU 0F7H
HOMEKEY EQU 0F8H
BREAKKEY EQU 0FBH
GRAPHKEY EQU 0FCH
ALPHAKEY EQU 0FDH
;-----------------------------------------------
; IO ports in hardware and values.
;-----------------------------------------------
MMCFG EQU 060H ; Memory management configuration latch.
SETXMHZ EQU 062H ; Select the alternate clock frequency.
SET2MHZ EQU 064H ; Select the system 2MHz clock frequency.
CLKSELRD EQU 066H ; Read clock selected setting, 0 = 2MHz, 1 = XMHz
SVCREQ EQU 068H ; I/O Processor service request.
CPLDSTATUS EQU 06BH ; Version 2.1 CPLD status register.
CPUCFG EQU 06CH ; Version 2.2 CPU configuration register.
CPUSTATUS EQU 06CH ; Version 2.2 CPU runtime status register.
CPUINFO EQU 06DH ; Version 2.2 CPU information register.
CPLDCFG EQU 06EH ; Version 2.1 CPLD configuration register.
CPLDINFO EQU 06FH ; Version 2.1 CPLD version information register.
VMPNUM EQU 0A0H ; Set the parameter number to update.
VMPLBYTE EQU 0A1H ; Update the lower selected parameter byte.
VMPUBYTE EQU 0A2H ; Update the upper selected parameter byte.
PALSLCTOFF EQU 0A3H ; set the palette slot Off position to be adjusted.
PALSLCTON EQU 0A4H ; set the palette slot On position to be adjusted.
PALSETRED EQU 0A5H ; set the red palette value according to the PALETTE_PARAM_SEL address.
PALSETGREEN EQU 0A6H ; set the green palette value according to the PALETTE_PARAM_SEL address.
PALSETBLUE EQU 0A7H ; set the blue palette value according to the PALETTE_PARAM_SEL address.
VMPALETTE EQU 0B0H ; Select Palette:
; 0xB0 sets the palette. The Video Module supports 4 bit per colour output but there is only enough RAM for 1 bit per colour so the pallette is used to change the colours output.
; Bits [7:0] defines the pallete number. This indexes a lookup table which contains the required 4bit output per 1bit input.
; GPU:
GPUPARAM EQU 0B2H ; 0xB2 set parameters. Store parameters in a long word to be used by the graphics command processor.
; The parameter word is 128 bit and each write to the parameter word shifts left by 8 bits and adds the new byte at bits 7:0.
GPUCMD EQU 0B3H ; 0xB3 set the graphics processor unit commands.
GPUSTATUS EQU 0B3H ; [7;1] - FSM state, [0] - 1 = busy, 0 = idle
; Bits [5:0] - 0 = Reset parameters.
; 1 = Clear to val. Start Location (16 bit), End Location (16 bit), Red Filter, Green Filter, Blue Filter
;
VMCTRL EQU 0B8H ; Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
VMGRMODE EQU 0B9H ; Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
VMREDMASK EQU 0BAH ; Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMGREENMASK EQU 0BBH ; Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMBLUEMASK EQU 0BCH ; Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMPAGE EQU 0BDH ; Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
VMVGATTR EQU 0BEH ; Select VGA Border colour and attributes. Bit 2 = Red, 1 = Green, 0 = Blue.
VMVGAMODE EQU 0BFH ; Select VGA output mode. Bits [3:0] - Output mode.
GDCRTC EQU 0CFH ; MZ-800 CRTC control register
GDCMD EQU 0CEH ; MZ-800 CRTC Mode register
GDGRF EQU 0CDH ; MZ-800 read format register
GDGWF EQU 0CCH ; MZ-800 write format register
MMIO0 EQU 0E0H ; MZ-700/MZ-800 Memory Management Set 0
MMIO1 EQU 0E1H ; MZ-700/MZ-800 Memory Management Set 1
MMIO2 EQU 0E2H ; MZ-700/MZ-800 Memory Management Set 2
MMIO3 EQU 0E3H ; MZ-700/MZ-800 Memory Management Set 3
MMIO4 EQU 0E4H ; MZ-700/MZ-800 Memory Management Set 4
MMIO5 EQU 0E5H ; MZ-700/MZ-800 Memory Management Set 5
MMIO6 EQU 0E6H ; MZ-700/MZ-800 Memory Management Set 6
MMIO7 EQU 0E7H ; MZ-700/MZ-800 Memory Management Set 7
SYSCTRL EQU 0F0H ; System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
GRAMMODE EQU 0F4H ; MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
;-----------------------------------------------
; CPLD Configuration constants.
;-----------------------------------------------
MODE_MZ80K EQU 0 ; Set to MZ-80K mode.
MODE_MZ80C EQU 1 ; Set to MZ-80C mode.
MODE_MZ1200 EQU 2 ; Set to MZ-1200 mode.
MODE_MZ80A EQU 3 ; Set to MZ-80A mode (base mode on MZ-80A hardware).
MODE_MZ700 EQU 4 ; Set to MZ-700 mode (base mode on MZ-700 hardware).
MODE_MZ800 EQU 5 ; Set to MZ-800 mode.
MODE_MZ80B EQU 6 ; Set to MZ-80B mode.
MODE_MZ2000 EQU 7 ; Set to MZ-2000 mode.
MODE_VIDEO_FPGA EQU 8 ; Bit flag (bit 3) to switch CPLD into using the new FPGA video hardware.
MODE_RESET_PRESERVE EQU 080H ; Preserve register configuration through reset.
;-----------------------------------------------
; CPLD Command Instruction constants.
;-----------------------------------------------
CPLD_RESET_HOST EQU 1 ; CPLD level command to reset the host system.
CPLD_HOLD_HOST_BUS EQU 2 ; CPLD command to hold the host bus.
CPLD_RELEASE_HOST_BUS EQU 3 ; CPLD command to release the host bus.
;-----------------------------------------------
; FPGA CPU enhancement control bits.
;-----------------------------------------------
CPUMODE_SET_Z80 EQU 000H ; Set the CPU to the hard Z80.
CPUMODE_SET_T80 EQU 001H ; Set the CPU to the soft T80.
CPUMODE_SET_ZPU_EVO EQU 002H ; Set the CPU to the soft ZPU Evolution.
CPUMODE_SET_AAA EQU 004H ; Place holder for a future soft CPU.
CPUMODE_SET_BBB EQU 008H ; Place holder for a future soft CPU.
CPUMODE_SET_CCC EQU 010H ; Place holder for a future soft CPU.
CPUMODE_SET_DDD EQU 020H ; Place holder for a future soft CPU.
CPUMODE_IS_Z80 EQU 000H ; Status value to indicate if the hard Z80 available.
CPUMODE_IS_T80 EQU 001H ; Status value to indicate if the soft T80 available.
CPUMODE_IS_ZPU_EVO EQU 002H ; Status value to indicate if the soft ZPU Evolution available.
CPUMODE_IS_AAA EQU 004H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_BBB EQU 008H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_CCC EQU 010H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_DDD EQU 020H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_RESET_CPU EQU 080H ; Reset the soft CPU. Active high, when high the CPU is held in RESET, when low the CPU runs.
CPUMODE_IS_SOFT_AVAIL EQU 040H ; Marker to indicate if the underlying FPGA can support soft CPU's.
CPUMODE_IS_SOFT_MASK EQU 0C0H ; Mask to filter out the Soft CPU availability flags.
CPUMODE_IS_CPU_MASK EQU 03FH ; Mask to filter out which soft CPU's are available.
;-----------------------------------------------
; Video Module control bits.
;-----------------------------------------------
MODE_80CHAR EQU 010H ; Enable 80 character display.
MODE_COLOUR EQU 020H ; Enable colour display.
SYSMODE_MZ80A EQU 000H ; System board mode MZ80A, 2MHz CPU/Bus.
SYSMODE_MZ80B EQU 020H ; System board mode MZ80B, 4MHz CPU/Bus.
SYSMODE_MZ2000 EQU 020H ; System board mode MZ2000, 4MHz CPU/Bus.
SYSMODE_MZ700 EQU 042H ; System board mode MZ700, 3.54MHz CPU/Bus.
VMMODE_MZ80K EQU 000H ; Video mode = MZ80K
VMMODE_MZ80C EQU 001H ; Video mode = MZ80C
VMMODE_MZ1200 EQU 002H ; Video mode = MZ1200
VMMODE_MZ80A EQU 003H ; Video mode = MZ80A
VMMODE_MZ700 EQU 004H ; Video mode = MZ700
VMMODE_MZ800 EQU 005H ; Video mode = MZ800
VMMODE_MZ1500 EQU 006H ; Video mode = MZ1500
VMMODE_MZ80B EQU 007H ; Video mode = MZ80B
VMMODE_MZ2000 EQU 008H ; Video mode = MZ2000
VMMODE_MZ2200 EQU 009H ; Video mode = MZ2200
VMMODE_MZ2500 EQU 00AH ; Video mode = MZ2500
VMMODE_PCGRAM EQU 020H ; Enable PCG RAM.
VMMODE_VGA_OFF EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT50 EQU 001H ; Set VGA mode off, external monitor is driven by standard internal 50Hz signals.
VMMODE_VGA_640x480 EQU 002H ; Set external monitor to VGA 640x480 @ 60Hz mode.
VMMODE_VGA_800x600 EQU 003H ; Set external monitor to VGA 800x600 @ 60Hz mode.
;-----------------------------------------------
; GPU commands.
;-----------------------------------------------
GPUCLEARVRAM EQU 001H ; Clear the VRAM without updating attributes.
GPUCLEARVRAMCA EQU 002H ; Clear the VRAM/ARAM with given attribute byte,
GPUCLEARVRAMP EQU 003H ; Clear the VRAM/ARAM with parameters.
GPUCLEARGRAM EQU 081H ; Clear the entire Framebuffer.
GPUCLEARGRAMP EQU 082H ; Clear the Framebuffer according to parameters.
GPURESET EQU 0FFH ; Reset the GPU, return to idle state.
;-----------------------------------------------
; tranZPUter SW Memory Management modes
;-----------------------------------------------
TZMM_ENIOWAIT EQU 020H ; Memory management IO Wait State enable - insert a wait state when an IO operation to E0-FF is executed.
TZMM_ORIG EQU 000H ; Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
TZMM_BOOT EQU 001H ; Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
TZMM_TZFS EQU 002H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
TZMM_TZFS2 EQU 003H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
TZMM_TZFS3 EQU 004H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
TZMM_TZFS4 EQU 005H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
TZMM_CPM EQU 006H + TZMM_ENIOWAIT ; 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.
TZMM_CPM2 EQU 007H + TZMM_ENIOWAIT ; 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, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
TZMM_COMPAT EQU 008H + TZMM_ENIOWAIT ; Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
TZMM_HOSTACCESS EQU 009H + TZMM_ENIOWAIT ; Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
TZMM_MZ700_0 EQU 00AH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_1 EQU 00BH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_2 EQU 00CH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_3 EQU 00DH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_4 EQU 00EH + TZMM_ENIOWAIT ; 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.
TZMM_MZ800 EQU 00FH + TZMM_ENIOWAIT ; MZ800 Mode - Tracks original hardware mode offering MZ700/MZ800 configurations.
TZMM_MZ2000 EQU 010H + TZMM_ENIOWAIT; ; MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
TZMM_FPGA EQU 015H + TZMM_ENIOWAIT ; Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
TZMM_TZPUM EQU 016H + TZMM_ENIOWAIT ; Everything in on mainboard, no access to tranZPUter memory.
TZMM_TZPU EQU 017H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU0 EQU 018H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU1 EQU 019H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
;TZMM_TZPU2 EQU 01AH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
;TZMM_TZPU3 EQU 01BH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
;TZMM_TZPU4 EQU 01CH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
;TZMM_TZPU5 EQU 01DH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
;TZMM_TZPU6 EQU 01EH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
;TZMM_TZPU7 EQU 01FH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
;-----------------------------------------------
; TZ File System Header (MZF)
;-----------------------------------------------
TZFS_ATRB: EQU 00000h ; Code Type, 01 = Machine Code.
TZFS_NAME: EQU 00001h ; Title/Name (17 bytes).
TZFS_SIZE: EQU 00012h ; Size of program.
TZFS_DTADR: EQU 00014h ; Load address of program.
TZFS_EXADR: EQU 00016h ; Exec address of program.
TZFS_COMNT: EQU 00018h ; Comment
TZFS_MZFLEN: EQU 128 ; Length of the MZF header.
TZFS_CMTLEN: EQU 104 ; Length of the comment field
;-----------------------------------------------
; BIOS WORK AREA (MZ80A)
;-----------------------------------------------
; Variables and control structure used by the I/O processor for service calls and requests.
ORG TZSVCMEM
TZSVCMEM: EQU 0FD80H ; Start of a memory structure used to communicate with the K64F I/O processor for services such as disk access.
TZSVCSIZE: EQU 00280H ;
TZSVCDIRSZ: EQU 20 ; Size of the directory/file name.
TZSVCFILESZ: EQU 17 ; Size of a Sharp filename.
TZSVCLONGFILESZ: EQU 31 ; Size of a standard filename.
TZSVCLONGFMTSZ: EQU 20 ; Size of a formatted standard filename for use in directory listings.
TZSVCWILDSZ: EQU 20 ; Size of the wildcard.
TZSVCSECSIZE: EQU 512
TZSVCDIR_ENTSZ: EQU 32 ; Size of a directory entry.
TZSVCWAITIORETRIES: EQU 500 ; Wait retries for IO response.
TZSVCWAITCOUNT: EQU 65535 ; Wait retries for IO request response.
TZSVC_FTYPE_MZF: EQU 0 ; File type being handled is an MZF
TZSVC_FTYPE_MZFHDR: EQU 1 ; File type being handled is an MZF Header.
TZSVC_FTYPE_CAS: EQU 2 ; File type being handled is an CASsette BASIC script.
TZSVC_FTYPE_BAS: EQU 3 ; File type being handled is an BASic script
TZSVC_FTYPE_ALL: EQU 10 ; Handle any filetype.
TZSVC_FTYPE_ALLFMT: EQU 11 ; Special case for directory listings, all files but truncated and formatted.
TZSVCCMD: DS virtual 1 ; Service command.
TZSVCRESULT: DS virtual 1 ; Service command result.
TZSVCDIRSEC: DS virtual 1 ; Storage for the directory sector number.
TZSVC_FILE_SEC: EQU TZSVCDIRSEC ; Union of the file and directory sector as only one can be used at a time.
TZSVC_TRACK_NO: DS virtual 2 ; Storage for the virtual drive track number.
TZSVC_SECTOR_NO: DS virtual 2 ; Storage for the virtual drive sector number.
TZSVC_FILE_NO: DS virtual 1 ; File number to be opened in a file service command.
TZSVC_FILE_TYPE: DS virtual 1 ; Type of file being accessed to differentiate between Sharp MZF files and other handled files.
TZSVC_LOADADDR: DS virtual 2 ; Dynamic load address for rom/images.
TZSVC_SAVEADDR: EQU TZSVC_LOADADDR ; Union of the load address and the cpu frequency change value, the address of data to be saved.
TZSVC_CPU_FREQ: EQU TZSVC_LOADADDR ; Union of the load address and the save address value, only one can be used at a time.
TZSVC_LOADSIZE: DS virtual 2 ; Size of image to load.
TZSVC_SAVESIZE: EQU TZSVC_LOADSIZE ; Size of image to be saved.
TZSVC_DIRNAME: DS virtual TZSVCDIRSZ ; Service directory/file name.
TZSVC_FILENAME: DS virtual TZSVCFILESZ ; Filename to be opened/created.
TZSVCWILDC: DS virtual TZSVCWILDSZ ; Directory wildcard for file pattern matching.
TZSVCSECTOR: DS virtual TZSVCSECSIZE ; Service command sector - to store directory entries, file sector read or writes.
TZSVC_CMD_READDIR EQU 01H ; Service command to open a directory and return the first block of entries.
TZSVC_CMD_NEXTDIR EQU 02H ; Service command to return the next block of an open directory.
TZSVC_CMD_READFILE EQU 03H ; Service command to open a file and return the first block.
TZSVC_CMD_NEXTREADFILE EQU 04H ; Service command to return the next block of an open file.
TZSVC_CMD_WRITEFILE EQU 05H ; Service command to create a file and save the first block.
TZSVC_CMD_NEXTWRITEFILE EQU 06H ; Service command to write the next block to the open file.
TZSVC_CMD_CLOSE EQU 07H ; Service command to close any open file or directory.
TZSVC_CMD_LOADFILE EQU 08H ; Service command to load a file directly into tranZPUter memory.
TZSVC_CMD_SAVEFILE EQU 09H ; Service command to save a file directly from tranZPUter memory.
TZSVC_CMD_ERASEFILE EQU 0aH ; Service command to erase a file on the SD card.
TZSVC_CMD_CHANGEDIR EQU 0bH ; Service command to change the active directory on the SD card.
TZSVC_CMD_LOAD40ABIOS EQU 20H ; Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD80ABIOS EQU 21H ; Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD700BIOS40 EQU 22H ; Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
TZSVC_CMD_LOAD700BIOS80 EQU 23H ; Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
TZSVC_CMD_LOAD80BIPL EQU 24H ; Service command requesting the MZ-80B IPL is loaded.
TZSVC_CMD_LOAD800BIOS EQU 25H ; Service command requesting that the MZ800 9Z-504M BIOS is loaded.
TZSVC_CMD_LOAD2000IPL EQU 26H ; Service command requesting the MZ-2000 IPL is loaded.
TZSVC_CMD_LOADTZFS EQU 2FH ; Service command requesting the loading of TZFS. This service is for machines which normally dont have a monitor BIOS. ie. MZ-80B/MZ-2000 and manually request TZFS.
TZSVC_CMD_LOADBDOS EQU 30H ; Service command to reload CPM BDOS+CCP.
TZSVC_CMD_ADDSDDRIVE EQU 31H ; Service command to attach a CPM disk to a drive number.
TZSVC_CMD_READSDDRIVE EQU 32H ; Service command to read an attached SD file as a CPM disk drive.
TZSVC_CMD_WRITESDDRIVE EQU 33H ; Service command to write to a CPM disk drive which is an attached SD file.
TZSVC_CMD_CPU_BASEFREQ EQU 40H ; Service command to switch to the mainboard frequency.
TZSVC_CMD_CPU_ALTFREQ EQU 41H ; Service command to switch to the alternate frequency provided by the K64F.
TZSVC_CMD_CPU_CHGFREQ EQU 42H ; Service command to set the alternate frequency in hertz.
TZSVC_CMD_CPU_SETZ80 EQU 50H ; Service command to switch to the external Z80 hard cpu.
TZSVC_CMD_CPU_SETT80 EQU 51H ; Service command to switch to the internal T80 soft cpu.
TZSVC_CMD_CPU_SETZPUEVO EQU 52H ; Service command to switch to the internal ZPU Evolution soft cpu.
TZSVC_CMD_EMU_SETMZ80K EQU 53H ; Service command to switch to the internal Sharp MZ Series Emulation of the MZ80K.
TZSVC_CMD_EMU_SETMZ80C EQU 54H ; "" "" "" MZ80C.
TZSVC_CMD_EMU_SETMZ1200 EQU 55H ; "" "" "" MZ1200.
TZSVC_CMD_EMU_SETMZ80A EQU 56H ; "" "" "" MZ80A.
TZSVC_CMD_EMU_SETMZ700 EQU 57H ; "" "" "" MZ700.
TZSVC_CMD_EMU_SETMZ800 EQU 58H ; "" "" "" MZ800.
TZSVC_CMD_EMU_SETMZ1500 EQU 59H ; "" "" "" MZ1500.
TZSVC_CMD_EMU_SETMZ80B EQU 5AH ; "" "" "" MZ80B.
TZSVC_CMD_EMU_SETMZ2000 EQU 5BH ; "" "" "" MZ2000.
TZSVC_CMD_EMU_SETMZ2200 EQU 5CH ; "" "" "" MZ2200.
TZSVC_CMD_EMU_SETMZ2500 EQU 5DH ; "" "" "" MZ2500.
TZSVC_CMD_EXIT EQU 07FH ; Service command to terminate TZFS and restart the machine in original mode.
TZSVC_STATUS_OK EQU 000H ; Flag to indicate the K64F processing completed successfully.
TZSVC_STATUS_REQUEST EQU 0FEH ; Flag to indicate the Z80 has made a request to the K64F.
TZSVC_STATUS_PROCESSING EQU 0FFH ; Flag to indicate the K64F is processing a command.

View File

@@ -0,0 +1,316 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: TESTTZ_Definitions.asm
;- Created: June 2020
;- Author(s): Philip Smart
;- Description: tranZPUter tester program
;- A small program to exercise parts of the tranZPUter to aid in problem resolution.
;-
;- Credits:
;- Copyright: (c) 2019-20 Philip Smart <philip.smart@net2net.org>
;-
;- History: Jun 2020 - Initial version.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;-----------------------------------------------
; Features.
;-----------------------------------------------
;-----------------------------------------------
; Configurable settings.
;-----------------------------------------------
COLW: EQU 80 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
SCRLW: EQU COLW / 8 ; Number of 8 byte regions in a line for hardware scroll.
MODE80C: EQU 1
; Debugging
ENADEBUG EQU 0 ; Enable debugging logic, 1 = enable, 0 = disable
;-----------------------------------------------
; Memory mapped ports in hardware.
;-----------------------------------------------
SCRN: EQU 0D000H
ARAM: EQU 0D800H
DSPCTL: EQU 0DFFFH ; Screen 40/80 select register (bit 7)
KEYPA: EQU 0E000h
KEYPB: EQU 0E001h
KEYPC: EQU 0E002h
KEYPF: EQU 0E003h
CSTR: EQU 0E002h
CSTPT: EQU 0E003h
CONT0: EQU 0E004h
CONT1: EQU 0E005h
CONT2: EQU 0E006h
CONTF: EQU 0E007h
SUNDG: EQU 0E008h
TEMP: EQU 0E008h
MEMSW: EQU 0E00CH
MEMSWR: EQU 0E010H
INVDSP: EQU 0E014H
NRMDSP: EQU 0E015H
SCLDSP: EQU 0E200H
SCLBASE: EQU 0E2H
;-----------------------------------------------
; Common character definitions.
;-----------------------------------------------
SCROLL EQU 001H ;Set scroll direction UP.
BELL EQU 007H
SPACE EQU 020H
TAB EQU 009H ;TAB ACROSS (8 SPACES FOR SD-BOARD)
CR EQU 00DH
LF EQU 00AH
FF EQU 00CH
DELETE EQU 07FH
BACKS EQU 008H
SOH EQU 1 ; For XModem etc.
EOT EQU 4
ACK EQU 6
NAK EQU 015H
NUL EQU 000H
NULL EQU 000H
CTRL_A EQU 001H
CTRL_B EQU 002H
CTRL_C EQU 003H
CTRL_D EQU 004H
CTRL_E EQU 005H
CTRL_F EQU 006H
CTRL_G EQU 007H
CTRL_H EQU 008H
CTRL_I EQU 009H
CTRL_J EQU 00AH
CTRL_K EQU 00BH
CTRL_L EQU 00CH
CTRL_M EQU 00DH
CTRL_N EQU 00EH
CTRL_O EQU 00FH
CTRL_P EQU 010H
CTRL_Q EQU 011H
CTRL_R EQU 012H
CTRL_S EQU 013H
CTRL_T EQU 014H
CTRL_U EQU 015H
CTRL_V EQU 016H
CTRL_W EQU 017H
CTRL_X EQU 018H
CTRL_Y EQU 019H
CTRL_Z EQU 01AH
ESC EQU 01BH
CTRL_SLASH EQU 01CH
CTRL_RB EQU 01DH
CTRL_CAPPA EQU 01EH
CTRL_UNDSCR EQU 01FH
CTRL_AT EQU 000H
NOKEY EQU 0F0H
CURSRIGHT EQU 0F1H
CURSLEFT EQU 0F2H
CURSUP EQU 0F3H
CURSDOWN EQU 0F4H
DBLZERO EQU 0F5H
INSERT EQU 0F6H
CLRKEY EQU 0F7H
HOMEKEY EQU 0F8H
BREAKKEY EQU 0FBH
;-----------------------------------------------
; IO ports in hardware and values.
;-----------------------------------------------
MMCFG EQU 060H ; Memory management configuration latch.
SETXMHZ EQU 062H ; Select the alternate clock frequency.
SET2MHZ EQU 064H ; Select the system 2MHz clock frequency.
CLKSELRD EQU 066H ; Read clock selected setting, 0 = 2MHz, 1 = XMHz
SVCREQ EQU 068H ; I/O Processor service request.
CPLDSTATUS EQU 06BH ; Version 2.1 CPLD status register.
CPUCFG EQU 06CH ; Version 2.2 CPU configuration register.
CPUSTATUS EQU 06CH ; Version 2.2 CPU runtime status register.
CPUINFO EQU 06DH ; Version 2.2 CPU information register.
CPLDCFG EQU 06EH ; Version 2.1 CPLD configuration register.
CPLDINFO EQU 06FH ; Version 2.1 CPLD version information register.
VMPNUM EQU 0A0H ; Set the parameter number to update.
VMPLBYTE EQU 0A1H ; Update the lower selected parameter byte.
VMPUBYTE EQU 0A2H ; Update the upper selected parameter byte.
PALSLCTOFF EQU 0A3H ; set the palette slot Off position to be adjusted.
PALSLCTON EQU 0A4H ; set the palette slot On position to be adjusted.
PALSETRED EQU 0A5H ; set the red palette value according to the PALETTE_PARAM_SEL address.
PALSETGREEN EQU 0A6H ; set the green palette value according to the PALETTE_PARAM_SEL address.
PALSETBLUE EQU 0A7H ; set the blue palette value according to the PALETTE_PARAM_SEL address.
VMPALETTE EQU 0B0H ; Select Palette:
; 0xB0 sets the palette. The Video Module supports 4 bit per colour output but there is only enough RAM for 1 bit per colour so the pallette is used to change the colours output.
; Bits [7:0] defines the pallete number. This indexes a lookup table which contains the required 4bit output per 1bit input.
; GPU:
GPUPARAM EQU 0B2H ; 0xB2 set parameters. Store parameters in a long word to be used by the graphics command processor.
; The parameter word is 128 bit and each write to the parameter word shifts left by 8 bits and adds the new byte at bits 7:0.
GPUCMD EQU 0B3H ; 0xB3 set the graphics processor unit commands.
GPUSTATUS EQU 0B3H ; [7;1] - FSM state, [0] - 1 = busy, 0 = idle
; Bits [5:0] - 0 = Reset parameters.
; 1 = Clear to val. Start Location (16 bit), End Location (16 bit), Red Filter, Green Filter, Blue Filter
;
VMCTRL EQU 0B8H ; Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
VMGRMODE EQU 0B9H ; Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
VMREDMASK EQU 0BAH ; Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMGREENMASK EQU 0BBH ; Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMBLUEMASK EQU 0BCH ; Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMPAGE EQU 0BDH ; Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
VMVGATTR EQU 0BEH ; Select VGA Border colour and attributes. Bit 2 = Red, 1 = Green, 0 = Blue.
VMVGAMODE EQU 0BFH ; Select VGA output mode. Bits [3:0] - Output mode.
GDCRTC EQU 0CFH ; MZ-800 CRTC control register
GDCMD EQU 0CEH ; MZ-800 CRTC Mode register
GDGRF EQU 0CDH ; MZ-800 read format register
GDGWF EQU 0CCH ; MZ-800 write format register
MMIO0 EQU 0E0H ; MZ-700/MZ-800 Memory Management Set 0
MMIO1 EQU 0E1H ; MZ-700/MZ-800 Memory Management Set 1
MMIO2 EQU 0E2H ; MZ-700/MZ-800 Memory Management Set 2
MMIO3 EQU 0E3H ; MZ-700/MZ-800 Memory Management Set 3
MMIO4 EQU 0E4H ; MZ-700/MZ-800 Memory Management Set 4
MMIO5 EQU 0E5H ; MZ-700/MZ-800 Memory Management Set 5
MMIO6 EQU 0E6H ; MZ-700/MZ-800 Memory Management Set 6
MMIO7 EQU 0E7H ; MZ-700/MZ-800 Memory Management Set 7
SYSCTRL EQU 0F0H ; System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
GRAMMODE EQU 0F4H ; MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
;-----------------------------------------------
; CPLD Configuration constants.
;-----------------------------------------------
MODE_MZ80K EQU 0 ; Set to MZ-80K mode.
MODE_MZ80C EQU 1 ; Set to MZ-80C mode.
MODE_MZ1200 EQU 2 ; Set to MZ-1200 mode.
MODE_MZ80A EQU 3 ; Set to MZ-80A mode (base mode on MZ-80A hardware).
MODE_MZ700 EQU 4 ; Set to MZ-700 mode (base mode on MZ-700 hardware).
MODE_MZ800 EQU 5 ; Set to MZ-800 mode.
MODE_MZ80B EQU 6 ; Set to MZ-80B mode.
MODE_MZ2000 EQU 7 ; Set to MZ-2000 mode.
MODE_VIDEO_FPGA EQU 8 ; Bit flag (bit 3) to switch CPLD into using the new FPGA video hardware.
MODE_RESET_PRESERVE EQU 080H ; Preserve register configuration through reset.
;-----------------------------------------------
; CPLD Command Instruction constants.
;-----------------------------------------------
CPLD_RESET_HOST EQU 1 ; CPLD level command to reset the host system.
CPLD_HOLD_HOST_BUS EQU 2 ; CPLD command to hold the host bus.
CPLD_RELEASE_HOST_BUS EQU 3 ; CPLD command to release the host bus.
;-----------------------------------------------
; FPGA CPU enhancement control bits.
;-----------------------------------------------
CPUMODE_SET_Z80 EQU 000H ; Set the CPU to the hard Z80.
CPUMODE_SET_T80 EQU 001H ; Set the CPU to the soft T80.
CPUMODE_SET_ZPU_EVO EQU 002H ; Set the CPU to the soft ZPU Evolution.
CPUMODE_SET_EMU_MZ EQU 004H ; Set the hardware to enable the Sharp MZ Series emulations.
CPUMODE_SET_BBB EQU 008H ; Place holder for a future soft CPU.
CPUMODE_SET_CCC EQU 010H ; Place holder for a future soft CPU.
CPUMODE_SET_DDD EQU 020H ; Place holder for a future soft CPU.
CPUMODE_IS_Z80 EQU 000H ; Status value to indicate if the hard Z80 available.
CPUMODE_IS_T80 EQU 001H ; Status value to indicate if the soft T80 available.
CPUMODE_IS_ZPU_EVO EQU 002H ; Status value to indicate if the soft ZPU Evolution available.
CPUMODE_IS_EMU_MZ EQU 004H ; Status value to indicate the Sharp MZ Series Hardware Emulation logic is available.
CPUMODE_IS_BBB EQU 008H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_CCC EQU 010H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_DDD EQU 020H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_RESET_CPU EQU 080H ; Reset the soft CPU. Active high, when high the CPU is held in RESET, when low the CPU runs.
CPUMODE_IS_SOFT_AVAIL EQU 040H ; Marker to indicate if the underlying FPGA can support soft CPU's.
CPUMODE_IS_SOFT_MASK EQU 0C0H ; Mask to filter out the Soft CPU availability flags.
CPUMODE_IS_CPU_MASK EQU 03FH ; Mask to filter out which soft CPU's are available.
;-----------------------------------------------
; Video Module control bits.
;-----------------------------------------------
MODE_80CHAR EQU 010H ; Enable 80 character display.
MODE_COLOUR EQU 020H ; Enable colour display.
SYSMODE_MZ80A EQU 000H ; System board mode MZ80A, 2MHz CPU/Bus.
SYSMODE_MZ80B EQU 020H ; System board mode MZ80B, 4MHz CPU/Bus.
SYSMODE_MZ2000 EQU 020H ; System board mode MZ2000, 4MHz CPU/Bus.
SYSMODE_MZ700 EQU 042H ; System board mode MZ700, 3.54MHz CPU/Bus.
VMMODE_MZ80K EQU 000H ; Video mode = MZ80K
VMMODE_MZ80C EQU 001H ; Video mode = MZ80C
VMMODE_MZ1200 EQU 002H ; Video mode = MZ1200
VMMODE_MZ80A EQU 003H ; Video mode = MZ80A
VMMODE_MZ700 EQU 004H ; Video mode = MZ700
VMMODE_MZ800 EQU 005H ; Video mode = MZ800
VMMODE_MZ1500 EQU 006H ; Video mode = MZ1500
VMMODE_MZ80B EQU 007H ; Video mode = MZ80B
VMMODE_MZ2000 EQU 008H ; Video mode = MZ2000
VMMODE_MZ2200 EQU 009H ; Video mode = MZ2200
VMMODE_MZ2500 EQU 00AH ; Video mode = MZ2500
VMMODE_PCGRAM EQU 020H ; Enable PCG RAM.
VMMODE_VGA_OFF EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT50 EQU 001H ; Set VGA mode off, external monitor is driven by standard internal 50Hz signals.
VMMODE_VGA_640x480 EQU 002H ; Set external monitor to VGA 640x480 @ 60Hz mode.
VMMODE_VGA_800x600 EQU 003H ; Set external monitor to VGA 800x600 @ 60Hz mode.
;-----------------------------------------------
; GPU commands.
;-----------------------------------------------
GPUCLEARVRAM EQU 001H ; Clear the VRAM without updating attributes.
GPUCLEARVRAMCA EQU 002H ; Clear the VRAM/ARAM with given attribute byte,
GPUCLEARVRAMP EQU 003H ; Clear the VRAM/ARAM with parameters.
GPUCLEARGRAM EQU 081H ; Clear the entire Framebuffer.
GPUCLEARGRAMP EQU 082H ; Clear the Framebuffer according to parameters.
GPURESET EQU 0FFH ; Reset the GPU, return to idle state.
;-----------------------------------------------
; tranZPUter SW Memory Management modes
;-----------------------------------------------
TZMM_ORIG EQU 000H ; Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
TZMM_BOOT EQU 001H ; Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
TZMM_TZFS EQU 002H ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
TZMM_TZFS2 EQU 003H ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
TZMM_TZFS3 EQU 004H ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
TZMM_TZFS4 EQU 005H ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
TZMM_CPM EQU 006H ; 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.
TZMM_CPM2 EQU 007H ; 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, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
TZMM_COMPAT EQU 008H + TZMM_ENIOWAIT ; Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
TZMM_HOSTACCESS EQU 009H + TZMM_ENIOWAIT ; Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
TZMM_MZ700_0 EQU 00AH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_1 EQU 00BH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_2 EQU 00CH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_3 EQU 00DH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_4 EQU 00EH + TZMM_ENIOWAIT ; 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.
TZMM_MZ800 EQU 00FH + TZMM_ENIOWAIT ; MZ800 Mode - Tracks original hardware mode offering MZ700/MZ800 configurations.
TZMM_MZ2000 EQU 010H + TZMM_ENIOWAIT; ; MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
TZMM_FPGA EQU 015H + TZMM_ENIOWAIT ; Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
TZMM_TZPUM EQU 016H + TZMM_ENIOWAIT ; Everything in on mainboard, no access to tranZPUter memory.
TZMM_TZPU EQU 017H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU0 EQU 018H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU1 EQU 019H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
;TZMM_TZPU2 EQU 01AH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
;TZMM_TZPU3 EQU 01BH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
;TZMM_TZPU4 EQU 01CH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
;TZMM_TZPU5 EQU 01DH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
;TZMM_TZPU6 EQU 01EH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
;TZMM_TZPU7 EQU 01FH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
;-----------------------------------------------
; TZ File System Header (MZF)
;-----------------------------------------------
TZFS_ATRB: EQU 00000h ; Code Type, 01 = Machine Code.
TZFS_NAME: EQU 00001h ; Title/Name (17 bytes).
TZFS_SIZE: EQU 00012h ; Size of program.
TZFS_DTADR: EQU 00014h ; Load address of program.
TZFS_EXADR: EQU 00016h ; Exec address of program.
TZFS_COMNT: EQU 00018h ; Comment
TZFS_MZFLEN: EQU 128 ; Length of the MZF header.
TZFS_CMTLEN: EQU 104 ; Length of the comment field
;-----------------------------------------------
; BIOS WORK AREA (MZ80A)
;-----------------------------------------------

View File

@@ -0,0 +1,362 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: TZFS_Definitions.asm
;- Created: September 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- Credits:
;- Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;- July 2020 - Updates to accommodate v2.1 of the tranZPUter board.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;-----------------------------------------------
; Features.
;-----------------------------------------------
BUILD_MZ80A EQU 0 ; Build for the standard Sharp MZ80A, no lower memory.
BUILD_MZ700 EQU 0 ; Build for the Sharp MZ-700 base hardware.
BUILD_MZ2000 EQU 1 ; Build for the Sharp MZ-2000 base hardware.
; Debugging
ENADEBUG EQU 0 ; Enable debugging logic, 1 = enable, 0 = disable
;-----------------------------------------------
; Entry/compilation start points.
;-----------------------------------------------
MROMADDR EQU 00000H ; Start of SA1510 Monitor ROM.
UROMADDR EQU 0E800H ; Start of User ROM Address space.
UROMBSTBL EQU UROMADDR + 020H ; Entry point to the bank switching table.
TZFSJMPTABLE EQU UROMADDR + 00080H ; Start of jump table.
BANKRAMADDR EQU 0F000H ; Start address of the banked RAM used for TZFS functionality.
FDCROMADDR EQU 0F000H
FDCJMP1 EQU 0F3FEH ; ROM paged vector 1.
FDCJMP2 EQU 0F7FEH ; ROM paged vector 2.
FDCJMP3 EQU 0F7FEH ; ROM paged vector 3.
FDCJMP4 EQU 0F7FEH ; ROM paged vector 4.
PRGBOOTJMP EQU 0CF00H ; Location to load bootstrap for original host program.
;-----------------------------------------------
; Common character definitions.
;-----------------------------------------------
SCROLL EQU 001H ;Set scroll direction UP.
BELL EQU 007H
SPACE EQU 020H
TAB EQU 009H ;TAB ACROSS (8 SPACES FOR SD-BOARD)
CR EQU 00DH
LF EQU 00AH
FF EQU 00CH
CS EQU 0CH ; Clear screen
DELETE EQU 07FH
BACKS EQU 008H
SOH EQU 1 ; For XModem etc.
EOT EQU 4
ACK EQU 6
NAK EQU 015H
NUL EQU 000H
NULL EQU 000H
CTRL_A EQU 001H
CTRL_B EQU 002H
CTRL_C EQU 003H
CTRL_D EQU 004H
CTRL_E EQU 005H
CTRL_F EQU 006H
CTRL_G EQU 007H
CTRL_H EQU 008H
CTRL_I EQU 009H
CTRL_J EQU 00AH
CTRL_K EQU 00BH
CTRL_L EQU 00CH
CTRL_M EQU 00DH
CTRL_N EQU 00EH
CTRL_O EQU 00FH
CTRL_P EQU 010H
CTRL_Q EQU 011H
CTRL_R EQU 012H
CTRL_S EQU 013H
CTRL_T EQU 014H
CTRL_U EQU 015H
CTRL_V EQU 016H
CTRL_W EQU 017H
CTRL_X EQU 018H
CTRL_Y EQU 019H
CTRL_Z EQU 01AH
ESC EQU 01BH
CTRL_SLASH EQU 01CH
CTRL_LB EQU 01BH
CTRL_RB EQU 01DH
CTRL_CAPPA EQU 01EH
CTRL_UNDSCR EQU 01FH
CTRL_AT EQU 000H
NOKEY EQU 0F0H
CURSRIGHT EQU 0F1H
CURSLEFT EQU 0F2H
CURSUP EQU 0F3H
CURSDOWN EQU 0F4H
DBLZERO EQU 0F5H
INSERT EQU 0F6H
CLRKEY EQU 0F7H
HOMEKEY EQU 0F8H
BREAKKEY EQU 0FBH
GRAPHKEY EQU 0FCH
ALPHAKEY EQU 0FDH
;-----------------------------------------------
; Memory mapped ports in hardware.
;-----------------------------------------------
SCRN: EQU 0D000H
ARAM: EQU 0D800H
DSPCTL: EQU 0DFFFH ; Screen 40/80 select register (bit 7)
KEYPA: EQU 0E000h
KEYPB: EQU 0E001h
KEYPC: EQU 0E002h
KEYPF: EQU 0E003h
CSTR: EQU 0E002h
CSTPT: EQU 0E003h
CONT0: EQU 0E004h
CONT1: EQU 0E005h
CONT2: EQU 0E006h
CONTF: EQU 0E007h
SUNDG: EQU 0E008h
TEMP: EQU 0E008h
MEMSW: EQU 0E00CH
MEMSWR: EQU 0E010H
INVDSP: EQU 0E014H
NRMDSP: EQU 0E015H
SCLDSP: EQU 0E200H
SCLBASE: EQU 0E2H
;-----------------------------------------------
; IO ports in hardware and values.
;-----------------------------------------------
MMCFG EQU 060H ; Memory management configuration latch.
SETXMHZ EQU 062H ; Select the alternate clock frequency.
SET2MHZ EQU 064H ; Select the system 2MHz clock frequency.
CLKSELRD EQU 066H ; Read clock selected setting, 0 = 2MHz, 1 = XMHz
SVCREQ EQU 068H ; I/O Processor service request.
CPLDSTATUS EQU 06BH ; Version 2.1 CPLD status register.
CPUCFG EQU 06CH ; Version 2.2 CPU configuration register.
CPUSTATUS EQU 06CH ; Version 2.2 CPU runtime status register.
CPUINFO EQU 06DH ; Version 2.2 CPU information register.
CPLDCFG EQU 06EH ; Version 2.1 CPLD configuration register.
CPLDINFO EQU 06FH ; Version 2.1 CPLD version information register.
VMPNUM EQU 0A0H ; Set the parameter number to update.
VMPLBYTE EQU 0A1H ; Update the lower selected parameter byte.
VMPUBYTE EQU 0A2H ; Update the upper selected parameter byte.
PALSLCTOFF EQU 0A3H ; set the palette slot Off position to be adjusted.
PALSLCTON EQU 0A4H ; set the palette slot On position to be adjusted.
PALSETRED EQU 0A5H ; set the red palette value according to the PALETTE_PARAM_SEL address.
PALSETGREEN EQU 0A6H ; set the green palette value according to the PALETTE_PARAM_SEL address.
PALSETBLUE EQU 0A7H ; set the blue palette value according to the PALETTE_PARAM_SEL address.
VMPALETTE EQU 0B0H ; Select Palette:
; 0xB0 sets the palette. The Video Module supports 4 bit per colour output but there is only enough RAM for 1 bit per colour so the pallette is used to change the colours output.
; Bits [7:0] defines the pallete number. This indexes a lookup table which contains the required 4bit output per 1bit input.
; GPU:
GPUPARAM EQU 0B2H ; 0xB2 set parameters. Store parameters in a long word to be used by the graphics command processor.
; The parameter word is 128 bit and each write to the parameter word shifts left by 8 bits and adds the new byte at bits 7:0.
GPUCMD EQU 0B3H ; 0xB3 set the graphics processor unit commands.
GPUSTATUS EQU 0B3H ; [7;1] - FSM state, [0] - 1 = busy, 0 = idle
; Bits [5:0] - 0 = Reset parameters.
; 1 = Clear to val. Start Location (16 bit), End Location (16 bit), Red Filter, Green Filter, Blue Filter
;
VMCTRL EQU 0B8H ; Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
VMGRMODE EQU 0B9H ; Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
VMREDMASK EQU 0BAH ; Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMGREENMASK EQU 0BBH ; Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMBLUEMASK EQU 0BCH ; Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMPAGE EQU 0BDH ; Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
VMVGATTR EQU 0BEH ; Select VGA Border colour and attributes. Bit 2 = Red, 1 = Green, 0 = Blue.
VMVGAMODE EQU 0BFH ; Select VGA output mode. Bits [3:0] - Output mode.
GDCRTC EQU 0CFH ; MZ-800 CRTC control register
GDCMD EQU 0CEH ; MZ-800 CRTC Mode register
GDGRF EQU 0CDH ; MZ-800 read format register
GDGWF EQU 0CCH ; MZ-800 write format register
MMIO0 EQU 0E0H ; MZ-700/MZ-800 Memory Management Set 0
MMIO1 EQU 0E1H ; MZ-700/MZ-800 Memory Management Set 1
MMIO2 EQU 0E2H ; MZ-700/MZ-800 Memory Management Set 2
MMIO3 EQU 0E3H ; MZ-700/MZ-800 Memory Management Set 3
MMIO4 EQU 0E4H ; MZ-700/MZ-800 Memory Management Set 4
MMIO5 EQU 0E5H ; MZ-700/MZ-800 Memory Management Set 5
MMIO6 EQU 0E6H ; MZ-700/MZ-800 Memory Management Set 6
MMIO7 EQU 0E7H ; MZ-700/MZ-800 Memory Management Set 7
SYSCTRL EQU 0F0H ; System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
GRAMMODE EQU 0F4H ; MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
;-----------------------------------------------
; CPLD Configuration constants.
;-----------------------------------------------
MODE_MZ80K EQU 0 ; Set to MZ-80K mode.
MODE_MZ80C EQU 1 ; Set to MZ-80C mode.
MODE_MZ1200 EQU 2 ; Set to MZ-1200 mode.
MODE_MZ80A EQU 3 ; Set to MZ-80A mode (base mode on MZ-80A hardware).
MODE_MZ700 EQU 4 ; Set to MZ-700 mode (base mode on MZ-700 hardware).
MODE_MZ800 EQU 5 ; Set to MZ-800 mode.
MODE_MZ80B EQU 6 ; Set to MZ-80B mode.
MODE_MZ2000 EQU 7 ; Set to MZ-2000 mode.
MODE_VIDEO_FPGA EQU 8 ; Bit flag (bit 3) to switch CPLD into using the new FPGA video hardware.
MODE_RESET_PRESERVE EQU 080H ; Preserve register configuration through reset.
;-----------------------------------------------
; CPLD Command Instruction constants.
;-----------------------------------------------
CPLD_RESET_HOST EQU 1 ; CPLD level command to reset the host system.
CPLD_HOLD_HOST_BUS EQU 2 ; CPLD command to hold the host bus.
CPLD_RELEASE_HOST_BUS EQU 3 ; CPLD command to release the host bus.
;-----------------------------------------------
; FPGA CPU enhancement control bits.
;-----------------------------------------------
CPUMODE_SET_Z80 EQU 000H ; Set the CPU to the hard Z80.
CPUMODE_SET_T80 EQU 001H ; Set the CPU to the soft T80.
CPUMODE_SET_ZPU_EVO EQU 002H ; Set the CPU to the soft ZPU Evolution.
CPUMODE_SET_EMU_MZ EQU 004H ; Set the hardware to enable the Sharp MZ Series emulations.
CPUMODE_SET_BBB EQU 008H ; Place holder for a future soft CPU.
CPUMODE_SET_CCC EQU 010H ; Place holder for a future soft CPU.
CPUMODE_SET_DDD EQU 020H ; Place holder for a future soft CPU.
CPUMODE_IS_Z80 EQU 000H ; Status value to indicate if the hard Z80 available.
CPUMODE_IS_T80 EQU 001H ; Status value to indicate if the soft T80 available.
CPUMODE_IS_ZPU_EVO EQU 002H ; Status value to indicate if the soft ZPU Evolution available.
CPUMODE_IS_EMU_MZ EQU 004H ; Status value to indicate the Sharp MZ Series Hardware Emulation logic is available.
CPUMODE_IS_BBB EQU 008H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_CCC EQU 010H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_IS_DDD EQU 020H ; Place holder to indicate if a future soft CPU is available.
CPUMODE_RESET_CPU EQU 080H ; Reset the soft CPU. Active high, when high the CPU is held in RESET, when low the CPU runs.
CPUMODE_IS_SOFT_AVAIL EQU 040H ; Marker to indicate if the underlying FPGA can support soft CPU's.
CPUMODE_IS_SOFT_MASK EQU 0C0H ; Mask to filter out the Soft CPU availability flags.
CPUMODE_IS_CPU_MASK EQU 03FH ; Mask to filter out which soft CPU's are available.
;-----------------------------------------------
; Video Module control bits.
;-----------------------------------------------
MODE_80CHAR EQU 010H ; Enable 80 character display.
MODE_COLOUR EQU 020H ; Enable colour display.
SYSMODE_MZ80A EQU 000H ; System board mode MZ80A, 2MHz CPU/Bus.
SYSMODE_MZ80B EQU 020H ; System board mode MZ80B, 4MHz CPU/Bus.
SYSMODE_MZ2000 EQU 020H ; System board mode MZ2000, 4MHz CPU/Bus.
SYSMODE_MZ700 EQU 042H ; System board mode MZ700, 3.54MHz CPU/Bus.
VMMODE_MZ80K EQU 000H ; Video mode = MZ80K
VMMODE_MZ80C EQU 001H ; Video mode = MZ80C
VMMODE_MZ1200 EQU 002H ; Video mode = MZ1200
VMMODE_MZ80A EQU 003H ; Video mode = MZ80A
VMMODE_MZ700 EQU 004H ; Video mode = MZ700
VMMODE_MZ800 EQU 005H ; Video mode = MZ800
VMMODE_MZ1500 EQU 006H ; Video mode = MZ1500
VMMODE_MZ80B EQU 007H ; Video mode = MZ80B
VMMODE_MZ2000 EQU 008H ; Video mode = MZ2000
VMMODE_MZ2200 EQU 009H ; Video mode = MZ2200
VMMODE_MZ2500 EQU 00AH ; Video mode = MZ2500
VMMODE_PCGRAM EQU 020H ; Enable PCG RAM.
VMMODE_VGA_OFF EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT EQU 000H ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT50 EQU 001H ; Set VGA mode off, external monitor is driven by standard internal 50Hz signals.
VMMODE_VGA_640x480 EQU 002H ; Set external monitor to VGA 640x480 @ 60Hz mode.
VMMODE_VGA_800x600 EQU 003H ; Set external monitor to VGA 800x600 @ 60Hz mode.
;-----------------------------------------------
; GPU commands.
;-----------------------------------------------
GPUCLEARVRAM EQU 001H ; Clear the VRAM without updating attributes.
GPUCLEARVRAMCA EQU 002H ; Clear the VRAM/ARAM with given attribute byte,
GPUCLEARVRAMP EQU 003H ; Clear the VRAM/ARAM with parameters.
GPUCLEARGRAM EQU 081H ; Clear the entire Framebuffer.
GPUCLEARGRAMP EQU 082H ; Clear the Framebuffer according to parameters.
GPURESET EQU 0FFH ; Reset the GPU, return to idle state.
;-----------------------------------------------
; tranZPUter SW Memory Management modes
;-----------------------------------------------
TZMM_ENIOWAIT EQU 020H ; Memory management IO Wait State enable - insert a wait state when an IO operation to E0-FF is executed.
TZMM_ORIG EQU 000H ; Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
TZMM_BOOT EQU 001H ; Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
TZMM_TZFS EQU 002H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
TZMM_TZFS2 EQU 003H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
TZMM_TZFS3 EQU 004H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
TZMM_TZFS4 EQU 005H + TZMM_ENIOWAIT ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
TZMM_CPM EQU 006H + TZMM_ENIOWAIT ; 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.
TZMM_CPM2 EQU 007H + TZMM_ENIOWAIT ; 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, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
TZMM_COMPAT EQU 008H + TZMM_ENIOWAIT ; Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
TZMM_HOSTACCESS EQU 009H + TZMM_ENIOWAIT ; Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
TZMM_MZ700_0 EQU 00AH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_1 EQU 00BH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_2 EQU 00CH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_3 EQU 00DH + TZMM_ENIOWAIT ; 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.
TZMM_MZ700_4 EQU 00EH + TZMM_ENIOWAIT ; 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.
TZMM_MZ800 EQU 00FH + TZMM_ENIOWAIT ; MZ800 Mode - Tracks original hardware mode offering MZ700/MZ800 configurations.
TZMM_MZ2000 EQU 010H + TZMM_ENIOWAIT; ; MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
TZMM_FPGA EQU 015H + TZMM_ENIOWAIT ; Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
TZMM_TZPUM EQU 016H + TZMM_ENIOWAIT ; Everything in on mainboard, no access to tranZPUter memory.
TZMM_TZPU EQU 017H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU0 EQU 018H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU1 EQU 019H + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
;TZMM_TZPU2 EQU 01AH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
;TZMM_TZPU3 EQU 01BH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
;TZMM_TZPU4 EQU 01CH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
;TZMM_TZPU5 EQU 01DH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
;TZMM_TZPU6 EQU 01EH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
;TZMM_TZPU7 EQU 01FH + TZMM_ENIOWAIT ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
;-----------------------------------------------
; TZ File System Header (MZF)
;-----------------------------------------------
TZFS_ATRB: EQU 00000h ; Code Type, 01 = Machine Code.
TZFS_NAME: EQU 00001h ; Title/Name (17 bytes).
TZFS_SIZE: EQU 00012h ; Size of program.
TZFS_DTADR: EQU 00014h ; Load address of program.
TZFS_EXADR: EQU 00016h ; Exec address of program.
TZFS_COMNT: EQU 00018h ; Comment
TZFS_MZFLEN: EQU 128 ; Length of the MZF header.
TZFS_CMTLEN: EQU 104 ; Length of the comment field
;-----------------------------------------------
; Entry/compilation start points.
;-----------------------------------------------
TPSTART: EQU 010F0h
MEMSTART: EQU 01200h
MSTART: EQU 0E900h
MZFHDRSZ EQU 128
TZFSSECTSZ EQU 256
MROMSIZE EQU 4096
UROMSIZE EQU 2048
FNSIZE EQU 17
;-----------------------------------------------
; RAM Banks, 0-3 are reserved for TZFS code in
; the User/Floppy ROM bank area.
;-----------------------------------------------
USRROMPAGES EQU 3 ; User ROM
ROMBANK0 EQU 0 ; TZFS Bank 0 - Main RFS Entry point and functions.
ROMBANK1 EQU 1 ; TZFS Bank 1 -
ROMBANK2 EQU 2 ; TZFS Bank 2 -
ROMBANK3 EQU 3 ; TZFS Bank 3 -
OBJCD EQU 001H ; MZF contains a binary object.
BTX1CD EQU 002H ; MZF contains a BASIC program.
BTX2CD EQU 005H ; MZF contains a BASIC program.
TZOBJCD0 EQU 0F8H ; MZF contains a TZFS binary object for page 0.
TZOBJCD1 EQU 0F9H
TZOBJCD2 EQU 0FAH
TZOBJCD3 EQU 0FBH
TZOBJCD4 EQU 0FCH
TZOBJCD5 EQU 0FDH
TZOBJCD6 EQU 0FEH
TZOBJCD7 EQU 0FFH ; MZF contains a TZFS binary object for page 7.

View File

@@ -0,0 +1,193 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: tzfs_mondef.asm
;- Created: September 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- This file contains the SA-1510/1Z-013A monitor specific definitions.
;-
;- Credits:
;- Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;- July 2020 - Updates to accommodate v2.1 of the tranZPUter board.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;-------------------------------------------------------
; Function entry points in the standard SA-1510 Monitor.
;-------------------------------------------------------
GETL: EQU 00003h
LETNL: EQU 00006h
NL: EQU 00009h
PRNTS: EQU 0000Ch
PRNT: EQU 00012h
MSG: EQU 00015h
MSGX: EQU 00018h
GETKY EQU 0001Bh
BRKEY EQU 0001Eh
?WRI EQU 00021h
?WRD EQU 00024h
?RDI EQU 00027h
?RDD EQU 0002Ah
?VRFY EQU 0002Dh
MELDY EQU 00030h
?TMST EQU 00033h
MONIT: EQU 00000h
;SS: EQU 00089h
;ST1: EQU 00095h
HLHEX EQU 00410h
_2HEX EQU 0041Fh
;?MODE: EQU 0074DH
;?KEY EQU 008CAh
PRNT3 EQU 0096Ch
?ADCN EQU 00BB9h
?DACN EQU 00BCEh
?DSP: EQU 00DB5H
?BLNK EQU 00DA6h
?DPCT EQU 00DDCh
PRTHL: EQU 003BAh
PRTHX: EQU 003C3h
HEX: EQU 003F9h
DPCT: EQU 00DDCh
;DLY12: EQU 00DA7h
;DLY12A: EQU 00DAAh
?RSTR1: EQU 00EE6h
;MOTOR: EQU 006A3H
CKSUM: EQU 0071AH
GAP: EQU 0077AH
;WTAPE: EQU 00485H
MSTOP: EQU 00700H
; ROM location differences between the MZ80A and MZ-700.
IF BUILD_MZ80A > 0
SS: EQU 00089h
ST1: EQU 00095h
WTAPE: EQU 00485H
MOTOR: EQU 006A3H
?MODE: EQU 0074DH
?KEY EQU 008CAh
DLY12: EQU 00DA7h
DLY12A: EQU 00DAAh
ELSE
SS: EQU 000A2H
ST1: EQU 000ADH
WTAPE: EQU 0048AH
MOTOR: EQU 0069FH
?MODE: EQU 0073EH
?KEY EQU 009B3H
DLY12: EQU 00996H
ENDIF
;-----------------------------------------------
; SA-1510 MONITOR WORK AREA (MZ80A)
;-----------------------------------------------
STACK: EQU 010F0H
;
ORG STACK
;
SPV:
IBUFE: ; TAPE BUFFER (128 BYTES)
ATRB: DS virtual 1 ; ATTRIBUTE
NAME: DS virtual FNSIZE ; FILE NAME
SIZE: DS virtual 2 ; BYTESIZE
DTADR: DS virtual 2 ; DATA ADDRESS
EXADR: DS virtual 2 ; EXECUTION ADDRESS
COMNT: DS virtual 92 ; COMMENT
SWPW: DS virtual 10 ; SWEEP WORK
KDATW: DS virtual 2 ; KEY WORK
KANAF: DS virtual 1 ; KANA FLAG (01=GRAPHIC MODE)
DSPXY: DS virtual 2 ; DISPLAY COORDINATES
MANG: DS virtual 6 ; COLUMN MANAGEMENT
MANGE: DS virtual 1 ; COLUMN MANAGEMENT END
PBIAS: DS virtual 1 ; PAGE BIAS
ROLTOP: DS virtual 1 ; ROLL TOP BIAS
MGPNT: DS virtual 1 ; COLUMN MANAG. POINTER
PAGETP: DS virtual 2 ; PAGE TOP
ROLEND: DS virtual 1 ; ROLL END
DS virtual 14 ; BIAS
FLASH: DS virtual 1 ; FLASHING DATA
SFTLK: DS virtual 1 ; SHIFT LOCK
REVFLG: DS virtual 1 ; REVERSE FLAG
SPAGE: DS virtual 1 ; PAGE CHANGE
FLSDT: DS virtual 1 ; CURSOR DATA
STRGF: DS virtual 1 ; STRING FLAG
DPRNT: DS virtual 1 ; TAB COUNTER
TMCNT: DS virtual 2 ; TAPE MARK COUNTER
SUMDT: DS virtual 2 ; CHECK SUM DATA
CSMDT: DS virtual 2 ; FOR COMPARE SUM DATA
AMPM: DS virtual 1 ; AMPM DATA
TIMFG: DS virtual 1 ; TIME FLAG
SWRK: DS virtual 1 ; KEY SOUND FLAG
TEMPW: DS virtual 1 ; TEMPO WORK
ONTYO: DS virtual 1 ; ONTYO WORK
OCTV: DS virtual 1 ; OCTAVE WORK
RATIO: DS virtual 2 ; ONPU RATIO
BUFER: DS virtual 81 ; GET LINE BUFFER
; Quickdisk work area
;QDPA EQU 01130h ; QD code 1
;QDPB EQU 01131h ; QD code 2
;QDPC EQU 01132h ; QD header startaddress
;QDPE EQU 01134h ; QD header length
;QDCPA EQU 0113Bh ; QD error flag
;HDPT EQU 0113Ch ; QD new headpoint possition
;HDPT0 EQU 0113Dh ; QD actual headpoint possition
;FNUPS EQU 0113Eh
;FNUPF EQU 01140h
;FNA EQU 01141h ; File Number A (actual file number)
;FNB EQU 01142h ; File Number B (next file number)
;MTF EQU 01143h ; QD motor flag
;RTYF EQU 01144h
;SYNCF EQU 01146h ; SyncFlags
;RETSP EQU 01147h
;BUFER EQU 011A3h
;QDIRBF EQU 0CD90h
;SPV:
;IBUFE: ; TAPE BUFFER (128 BYTES)
;ATRB: DS virtual 1 ; Code Type, 01 = Machine Code.
;NAME: DS virtual 17 ; Title/Name (17 bytes).
;SIZE: DS virtual 2 ; Size of program.
;DTADR: DS virtual 2 ; Load address of program.
;EXADR: DS virtual 2 ; Exec address of program.
;COMNT: DS virtual 104 ; COMMENT
;KANAF: DS virtual 1 ; KANA FLAG (01=GRAPHIC MODE)
;DSPXY: DS virtual 2 ; DISPLAY COORDINATES
;MANG: DS virtual 27 ; COLUMN MANAGEMENT
;FLASH: DS virtual 1 ; FLASHING DATA
;FLPST: DS virtual 2 ; FLASHING POSITION
;FLSST: DS virtual 1 ; FLASHING STATUS
;FLSDT: DS virtual 1 ; CURSOR DATA
;STRGF: DS virtual 1 ; STRING FLAG
;DPRNT: DS virtual 1 ; TAB COUNTER
;TMCNT: DS virtual 2 ; TAPE MARK COUNTER
;SUMDT: DS virtual 2 ; CHECK SUM DATA
;CSMDT: DS virtual 2 ; FOR COMPARE SUM DATA
;AMPM: DS virtual 1 ; AMPM DATA
;TIMFG: DS virtual 1 ; TIME FLAG
;SWRK: DS virtual 1 ; KEY SOUND FLAG
;TEMPW: DS virtual 1 ; TEMPO WORK
;ONTYO: DS virtual 1 ; ONTYO WORK
;OCTV: DS virtual 1 ; OCTAVE WORK
;RATIO: DS virtual 2 ; ONPU RATIO

View File

@@ -0,0 +1,123 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: tzfs_svcstruct.asm
;- Created: September 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- This file holds the TZFS service structure definition.
;-
;- Credits:
;- Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;- July 2020 - Updates to accommodate v2.1 of the tranZPUter board.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
TZSVC_CMD_READDIR EQU 01H ; Service command to open a directory and return the first block of entries.
TZSVC_CMD_NEXTDIR EQU 02H ; Service command to return the next block of an open directory.
TZSVC_CMD_READFILE EQU 03H ; Service command to open a file and return the first block.
TZSVC_CMD_NEXTREADFILE EQU 04H ; Service command to return the next block of an open file.
TZSVC_CMD_WRITEFILE EQU 05H ; Service command to create a file and save the first block.
TZSVC_CMD_NEXTWRITEFILE EQU 06H ; Service command to write the next block to the open file.
TZSVC_CMD_CLOSE EQU 07H ; Service command to close any open file or directory.
TZSVC_CMD_LOADFILE EQU 08H ; Service command to load a file directly into tranZPUter memory.
TZSVC_CMD_SAVEFILE EQU 09H ; Service command to save a file directly from tranZPUter memory.
TZSVC_CMD_ERASEFILE EQU 0aH ; Service command to erase a file on the SD card.
TZSVC_CMD_CHANGEDIR EQU 0bH ; Service command to change the active directory on the SD card.
TZSVC_CMD_LOAD40ABIOS EQU 20H ; Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD80ABIOS EQU 21H ; Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD700BIOS40 EQU 22H ; Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
TZSVC_CMD_LOAD700BIOS80 EQU 23H ; Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
TZSVC_CMD_LOAD80BIPL EQU 24H ; Service command requesting the MZ-80B IPL is loaded.
TZSVC_CMD_LOAD800BIOS EQU 25H ; Service command requesting that the MZ800 9Z-504M BIOS is loaded.
TZSVC_CMD_LOAD2KIPL EQU 26H ; Service command requesting the MZ-2000 IPL is loaded.
TZSVC_CMD_LOAD2KBASIC1 EQU 27H ; Service command to load BASIC 1Z-001 for the MZ-2000.
TZSVC_CMD_LOAD2KBASIC2 EQU 28H ; Service command to load BASIC 1Z-002 for the MZ-2000.
TZSVC_CMD_LOAD2KMON EQU 29H ; Service command to load Monitor 1Z001M for the MZ-2000 IPL.
TZSVC_CMD_LOADTZFS EQU 2FH ; Service command requesting the loading of TZFS. This service is for machines which normally dont have a monitor BIOS. ie. MZ-80B/MZ-2000 and manually request TZFS.
TZSVC_CMD_LOADBDOS EQU 30H ; Service command to reload CPM BDOS+CCP.
TZSVC_CMD_ADDSDDRIVE EQU 31H ; Service command to attach a CPM disk to a drive number.
TZSVC_CMD_READSDDRIVE EQU 32H ; Service command to read an attached SD file as a CPM disk drive.
TZSVC_CMD_WRITESDDRIVE EQU 33H ; Service command to write to a CPM disk drive which is an attached SD file.
TZSVC_CMD_CPU_BASEFREQ EQU 40H ; Service command to switch to the mainboard frequency.
TZSVC_CMD_CPU_ALTFREQ EQU 41H ; Service command to switch to the alternate frequency provided by the K64F.
TZSVC_CMD_CPU_CHGFREQ EQU 42H ; Service command to set the alternate frequency in hertz.
TZSVC_CMD_CPU_SETZ80 EQU 50H ; Service command to switch to the external Z80 hard cpu.
TZSVC_CMD_CPU_SETT80 EQU 51H ; Service command to switch to the internal T80 soft cpu.
TZSVC_CMD_CPU_SETZPUEVO EQU 52H ; Service command to switch to the internal ZPU Evolution soft cpu.
TZSVC_CMD_EMU_SETMZ80K EQU 53H ; Service command to switch to the internal Sharp MZ Series Emulation of the MZ80K.
TZSVC_CMD_EMU_SETMZ80C EQU 54H ; "" "" "" MZ80C.
TZSVC_CMD_EMU_SETMZ1200 EQU 55H ; "" "" "" MZ1200.
TZSVC_CMD_EMU_SETMZ80A EQU 56H ; "" "" "" MZ80A.
TZSVC_CMD_EMU_SETMZ700 EQU 57H ; "" "" "" MZ700.
TZSVC_CMD_EMU_SETMZ800 EQU 58H ; "" "" "" MZ800.
TZSVC_CMD_EMU_SETMZ1500 EQU 59H ; "" "" "" MZ1500.
TZSVC_CMD_EMU_SETMZ80B EQU 5AH ; "" "" "" MZ80B.
TZSVC_CMD_EMU_SETMZ2000 EQU 5BH ; "" "" "" MZ2000.
TZSVC_CMD_EMU_SETMZ2200 EQU 5CH ; "" "" "" MZ2200.
TZSVC_CMD_EMU_SETMZ2500 EQU 5DH ; "" "" "" MZ2500.
TZSVC_CMD_EXIT EQU 07FH ; Service command to terminate TZFS and restart the machine in original mode.
TZSVC_STATUS_OK EQU 000H ; Flag to indicate the K64F processing completed successfully.
TZSVC_STATUS_REQUEST EQU 0FEH ; Flag to indicate the Z80 has made a request to the K64F.
TZSVC_STATUS_PROCESSING EQU 0FFH ; Flag to indicate the K64F is processing a command.
; Variables and control structure used by the I/O processor for service calls and requests.
ORG TZSVCMEM
;TZSVCMEM: EQU 0ED80H ; Start of a memory structure used to communicate with the K64F I/O processor for services such as disk access.
TZSVCSIZE: EQU 00280H ;
TZSVCDIRSZ: EQU 20 ; Size of the directory/file name.
TZSVCFILESZ: EQU 17 ; Size of a Sharp filename.
TZSVCLONGFILESZ: EQU 31 ; Size of a standard filename.
TZSVCLONGFMTSZ: EQU 20 ; Size of a formatted standard filename for use in directory listings.
TZSVCWILDSZ: EQU 20 ; Size of the wildcard.
TZSVCSECSIZE: EQU 512
TZSVCDIR_ENTSZ: EQU 32 ; Size of a directory entry.
TZSVCWAITIORETRIES: EQU 5 ; Wait retries for IO response.
TZSVCWAITCOUNT: EQU 65535 ; Wait retries for IO request response.
TZSVC_FTYPE_MZF: EQU 0 ; File type being handled is an MZF
TZSVC_FTYPE_MZFHDR: EQU 1 ; File type being handled is an MZF Header.
TZSVC_FTYPE_CAS: EQU 2 ; File type being handled is an CASsette BASIC script.
TZSVC_FTYPE_BAS: EQU 3 ; File type being handled is an BASic script
TZSVC_FTYPE_ALL: EQU 10 ; Handle any filetype.
TZSVC_FTYPE_ALLFMT: EQU 11 ; Special case for directory listings, all files but truncated and formatted.
TZSVCCMD: DS virtual 1 ; Service command.
TZSVCRESULT: DS virtual 1 ; Service command result.
TZSVCDIRSEC: DS virtual 1 ; Storage for the directory sector number.
TZSVC_FILE_SEC: EQU TZSVCDIRSEC ; Union of the file and directory sector as only one can be used at a time.
TZSVC_TRACK_NO: DS virtual 2 ; Storage for the virtual drive track number.
TZSVC_SECTOR_NO: DS virtual 2 ; Storage for the virtual drive sector number.
TZSVC_SECTOR_LBA: EQU TZSVC_TRACK_NO ; Sector in 32bit LBA format.
TZSVC_MEM_TARGET: EQU TZSVC_TRACK_NO ; Memory command should target, 0 = tranZPUter, 1 = mainboard.
TZSVC_FILE_NO: DS virtual 1 ; File number to be opened in a file service command.
TZSVC_FILE_TYPE: DS virtual 1 ; Type of file being accessed to differentiate between Sharp MZF files and other handled files.
TZSVC_LOADADDR: DS virtual 2 ; Dynamic load address for rom/images.
TZSVC_SAVEADDR: EQU TZSVC_LOADADDR ; Union of the load address and the cpu frequency change value, the address of data to be saved.
TZSVC_CPU_FREQ: EQU TZSVC_LOADADDR ; Union of the load address and the save address value, only one can be used at a time.
TZSVC_LOADSIZE: DS virtual 2 ; Size of image to load.
TZSVC_SAVESIZE: EQU TZSVC_LOADSIZE ; Size of image to be saved.
TZSVC_DIRNAME: DS virtual TZSVCDIRSZ ; Service directory/file name.
TZSVC_FILENAME: DS virtual TZSVCFILESZ ; Filename to be opened/created.
TZSVCWILDC: DS virtual TZSVCWILDSZ ; Directory wildcard for file pattern matching.
TZSVCSECTOR: DS virtual TZSVCSECSIZE ; Service command sector - to store directory entries, file sector read or writes.

View File

@@ -0,0 +1,498 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: RFS_Utilities.asm
;- Created: September 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- Credits:
;- Copyright: (c) 2019-20 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
; Comparing Strings
; IN HL Address of string1.
; DE Address of string2.
; BC Max bytes to compare, 0x00 or 0x0d will early terminate.
; OUT zero Set if string1 = string2, reset if string1 != string2.
; carry Set if string1 > string2, reset if string1 <= string2.
CMPSTRING: IF USE_CMPSTRING = 1
PUSH HL
PUSH DE
CMPSTR1: LD A, (DE) ; Compare bytes.
CP 000h ; Check for end of string.
JR Z, CMPSTR3
CP 00Dh
JR Z, CMPSTR3
CPI ; Compare bytes.
JR NZ, CMPSTR2 ; If (HL) != (DE), abort.
INC DE ; Update pointer.
JP PE, CMPSTR1 ; Next byte if BC not zero.
CMPSTR2: DEC HL
CP (HL) ; Compare again to affect carry.
CMPSTR4: POP DE
POP HL
RET
CMPSTR3: LD A, (HL)
CP 000h ; Check for end of string.
JR Z, CMPSTR4
CP 00Dh
JR Z, CMPSTR4
SCF ; String 1 greater than string 2
JR CMPSTR4
ENDIF
; IN HL Address of source string, length-prefixed.
; DE Address of destination string, length-prefixed.
; B Start index. 1 = first character.
; C Length of substring to return.
;
; OUT carry Set if an error condition happened:
; If B is zero, then uses index of 1.
; If index > source length, an empty string is returned.
; If index + return length > source length, returns all
; characters from index to end-of-string.
SUBSTRING: IF USE_SUBSTRING = 1
PUSH DE ; It would be convenient to keep DE pointing to
; the start of the destination string
OR A ; Boolean OR resets carry
PUSH AF ; Save carry
LD A, B ; Is index beyond source length?
CP (HL)
DEC A ; Decrement A so NC can be used
JR NC,SUBST3
ADD A, C ; If index+len is > 255, error
JR C, SUBST1
INC A ; Increment A so C can be used
CP (HL) ; If index+len is beyond source length, then error
JR C, SUBST2
SUBST1: POP AF ; Set carry flag
SCF
PUSH AF
LD A, (HL) ; Get source length
SUB B ; Subtract start index
INC A ; Compensate
LD C, A ; New size of string
SUBST2: LD A, C ; Size of sting to get
LD (DE), A ; Save length index
INC DE ; To body of string
LD A, B ; Get index
LD B, 0 ; Zero-extend BC for LDIR
ADD A, L ; This is a sneaky way to add A to HL
LD L, A ; without using up another 16-bit register
ADC A, H ;
SUB L ;
LD H, A ;
LDIR ; Copy substring over
POP AF ; Restore flags
POP DE ; Restore destination
RET
SUBST3: XOR A ; Set a length index of zero
LD (DE), A
POP AF ; Clean off stack and set carry
POP DE
SCF
RET
ENDIF
; IN HL Address of string to look in, length prefixed.
; DE Address of string to find, length prefixed.
;
; OUT
; If found:
; A Offset into look-up string where the target string was found.
; The first byte (ignoring length prefix) is offset 1.
; carry Reset.
;
; If not found:
; A = 0
; carry Set.
INDEX: IF USE_INDEX = 1
LD A, (DE) ; Abort if string to find is too big
CP (HL)
INC A
JR NC, IDXABORT
DEC A ; Save length of string to find
LD IXL, A
LD B, 0 ; Put length of string to search in BC
LD C, (HL)
INC HL ; Advance pointers
INC DE
PUSH HL ; Save start of search string
IDXRST: PUSH DE ; Save start of key string
LD A, IXL ; Initialize matched characters counter
LD IXH, A
LD A, (DE) ; Get a character to match
CPIR ; Look for it
JR NZ, IDXNF ; Abort if not found
IDXLOOP: DEC IXH ; Update counter and see if done
JR Z, IDXFOUND
INC DE ; Get next character in key string
LD A, (DE)
CPI ; See if it matches next char in master
JR Z, IDXLOOP
JP PO, IDXNF ; Abort if we ran out of characters
POP DE ; If a mismatch, restart from the beginning
JR IDXRST
IDXNF: POP DE ; Clean stack
POP HL
IDXABORT: XOR A ; Report failure
SCF
RET
IDXFOUND: POP DE
POP BC ; BC = address of master
XOR A ; Put size of key string in DE
LD D, A
LD E, IXL
SBC HL, DE ; Find index
SBC HL, BC
LD A, L
INC A
RET
ENDIF
; IN HL Address of string to be inserted
; DE Address of string to receive insertion
; C Index. Start of string is 0
; OUT
; If successful:
; carry Reset
; HL Input DE
; If unsuccessful:
; carry Set. If new string length is > 255.
;
; Notes If index > string length, string is appended.
; Data after the string is destroyed.
STRINSERT: IF USE_STRINSERT = 1
LD A, (DE)
LD B, A
INC A
CP C
JR NC, STRINSERT1
LD C, B
STRINSERT1:DEC A
ADD A, (HL)
RET C
LD (DE), A ; Update length
PUSH DE ; Make room
PUSH HL
LD A, (HL)
INC C
LD H, 0
LD L, C
ADD HL, DE
LD D, H
LD E, L
PUSH AF
ADD A, E
LD E, A
ADC A, D
SUB E
LD D, A
POP AF
LD B, 0
LD C, A
PUSH HL
LDIR
POP DE ; Copy string over
POP HL
LD C, (HL)
INC HL
LDIR
POP HL
RET
ENDIF
; IN HL Address of string.
; B Index of first character to delete. First character is 0.
; C Number of characters to kill.
; OUT
; If successful:
; carry Reset
; If unsuccessful:
; carry Set
;
; Notes If B > string length, then error.
; If B + C > string length, deletion
; stops at end of string.
STRDELETE: IF USE_STRDELETE = 1
LD A, B ; See if index is too big
CP (HL)
CCF ; Flip for error
RET C
ADD A, C ; See if too many chars on chopping block
CP (HL)
JR C, STRDELETE1
INC B ; Set index as length
LD (HL), B
RET
STRDELETE1:PUSH HL
LD A, (HL)
SUB C
LD (HL), A
INC HL
LD E, C
LD C, B
LD B, 0
ADD HL, BC
SUB C
LD C, E
LD D, H
LD E, L
ADD HL, BC
LD C, A
LDIR
POP HL
RET
ENDIF
; IN HL Address of first string.
; DE Address of second string.
; OUT
; If successful:
; carry Reset
; If unsuccessful:
; carry Set
;
; Notes If new string lenght is > 255, error.
; HL is saved.
CONCAT: IF USE_CONCAT = 1
LD A, (DE) ; Combine lengths
ADD A, (HL)
RET C
LD C, (HL)
LD (HL), A
LD B, 0
INC C
PUSH HL
ADD HL, BC
EX DE, HL
LD C, (HL)
INC HL
LDIR
POP HL
RET
ENDIF
; Utility: Convert character to upper case
; On entry: A = Character in either case
; On exit: A = Character in upper case
; BC DE HL IX IY I AF' BC' DE' HL' preserved
ConvertCharToUCase: IF USE_CNVUPPER = 1
CP 'a' ;Character less than 'a'?
RET C ;Yes, so finished
CP 'z'+1 ;Character greater than 'z'?
RET NC ;Yes, so finished
SUB 'a'-'A' ;Convert case
RET
ENDIF
;
; Utility: Convert character to numberic value
; On entry: A = ASCII character (0-9 or A-F)
; On exit: If character is a valid hex digit:
; A = Numberic value (0 to 15) and Z flagged
; If character is not a valid hex digit:
; A = 0xFF and NZ flagged
; BC DE HL IX IY I AF' BC' DE' HL' preserved
; Interrupts not enabled
ConvertCharToNumber: IF USE_CNVCHRTONUM = 1
CALL ConvertCharToUCase
CP '0' ;Character < '0'?
JR C,@Bad ;Yes, so no hex character
CP '9'+1 ;Character <= '9'?
JR C,@OK ;Yes, got hex character
CP 'A' ;Character < 'A'
JR C,@Bad ;Yes, so not hex character
CP 'F'+1 ;Character <= 'F'
JR C,@OK ;No, not hex
; Character is not a hex digit so return
@Bad: LD A,0FFh ;Return status: not hex character
OR A ; A = 0xFF and NZ flagged
RET
; Character is a hex digit so adjust from ASCII to number
@OK: SUB '0' ;Subtract '0'
CP 00Ah ;Number < 10 ?
JR C,@Finished ;Yes, so finished
SUB 007h ;Adjust for 'A' to 'F'
@Finished: CP A ;Return A = number (0 to 15) and Z flagged to
RET ; indicate character is a valid hex digital
ENDIF
; Utility: Is character numeric?
; On entry: A = ASCII character
; On exit: Carry flag set if character is numeric (0 to 9)
; A BC DE HL IX IY I AF' BC' DE' HL' preserved
IsCharNumeric: IF USE_ISNUMERIC = 1
CP '0' ;Less than '0'?
JR C,@Not2 ;Yes, so go return NOT numeric
CP '9'+1 ;Less than or equal to '9'?
RET C ;Yes, so numeric (C flagged)
@Not2: OR A ;No, so NOT numeric (NC flagged)
RET
ENDIF
; Utility: Convert hexadecimal or decimal text to number
; On entry: DE = Pointer to start of ASCII string
; On exit: If valid number found:
; A = 0 and Z flagged
; HL = Number found
; If valid number not found:
; A != 0 and NZ flagged
; HL = Not specified
; DE = Not specified
; HL = Number
; BC DE IX IY I AF' BC' DE' HL' preserved
; Hexadecmal numbers can be prefixed with either "$" or "0x"
; Decimal numbers must be prefixed with "+"
; A number without a prefix is assumed to be hexadecimal
; Hexadecimal number without a prefix must start with "0" to "9"
; ... this is to stop the assembler getting confused between
; ... register names and constants which could be fixed by
; ... re-ordering the (dis)assebmer's instruction table
; Numbers can be terminated with ")", space, null or control code
; Negative numbers, preceded with "-", are not supported
; Text must be terminated with ')', space or control char.
ConvertStringToNumber: IF USE_CNVSTRTONUM = 1
PUSH BC
LD HL,0 ;Build result here
LD A,(DE) ;Get character from string
CP '+' ;Does string start with '+' ?
JR Z,@Decimal ;Yes, so its decimal
CP '$' ;Does string start with '$' ?
JR Z,@Hdecimal ;Yes, so its hexadecimal
CP 39 ;Does string start with apostrophe?
JR Z,@Char ;Yes, so its a character
CP '"' ;Does string start with '"' ?
JR Z,@Char ;Yes, so its a character
; CALL IsCharNumeric ;Is first character '0' to '9' ?
; JR NC,@Failure ;No, so invalid number
; CALL IsCharHex ;Is first character hexadecimal ?
; JR NC,@Failure ;No, so invalid hex character
CP '0' ;Is first character '0' ?
; JR NZ,@HexNext ;No, so default to hexadecimal
JR NZ,@DecNext ;No, so default to decimal
INC DE ;Point to next character in string
LD A,(DE) ;Get character from string
CALL ConvertCharToUCase
CP 'X' ;Is second character 'x' ?
JR NZ,@HexNext ;No, so must be default format
; JR NZ,@DecNext ;No, so must be default format
; Hexadecimal number...
@Hdecimal: INC DE ;Point to next character in string
@HexNext: LD A,(DE) ;Get character from string
CP ')' ;Terminated with a bracket?
JR Z,@Success ;yes, so success
CP 32+1 ;Space or control character?
JR C,@Success ;Yes, so successld hl
CALL ConvertCharToNumber ;Convert character to number
JR NZ,@Failure ;Return if failure (NZ flagged)
INC DE ;Point to next character in string
ADD HL,HL ;Current result = 16 * current result..
ADD HL,HL
ADD HL,HL
ADD HL,HL
OR L ;Add new number (0 to 15)..
LD L,A
JR @HexNext
; Decimal number...
@Decimal: INC DE ;Point to next character in string
@DecNext: LD A,(DE) ;Get character from string
CP ')' ;Terminated with a bracket?
JR Z,@Success ;yes, so success
CP 32+1 ;Space or control character?
JR C,@Success ;Yes, so success
CALL IsCharNumeric ;Is first character '0' to '9' ?
JR NC,@Failure ;No, so invalid number
CALL ConvertCharToNumber ;Convert character to number
JR NZ,@Failure ;Return if failure (NZ flagged)
INC DE ;Point to next character in string
PUSH DE
LD B,9 ;Current result = 10 * current result..
LD D,H
LD E,L
@DecLoop: ADD HL,DE ;Add result to itself 9 times
DJNZ @DecLoop
POP DE
ADD A,L ;Add new number (0 to 15)..
LD L,A
JR NC,@DecNext
INC H
JR @DecNext
; Character...
@Char: INC DE ;Point to next character in string
LD A,(DE) ;Get ASCII character
LD L,A ;Store ASCII value as result
LD H,0
; JR @Success
; Return result...
@Success: POP BC
XOR A ;Return success with A = 0 and Z flagged
RET
@Failure: POP BC
LD A,0FFh ;Return failure with A != 0
OR A ; and NZ flagged
RET
ENDIF

View File

@@ -0,0 +1,77 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: tzfs_variales.asm
;- Created: September 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- This file holds the TZFS variable definitions.
;-
;- Credits:
;- Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;- July 2020 - Updates to accommodate v2.1 of the tranZPUter board.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
; Starting EC80H - variables used by the filing system.
ORG TZVARMEM
;TZVARMEM: EQU 0EC80H
;TZVARSIZE: EQU 00100H
WARMSTART: DS virtual 1 ; Warm start mode, 0 = cold start, 1 = warm start.
SCRNMODE: DS virtual 1 ; Mode of screen, [0] = 0 - 40 char, 1 - 80 char, [1] = 0 - Mainboard video, 1 - FPGA Video, [2] = 1 set VGA mode, 0 = standard, [7:4] Video mode.
SCRNMODE2: DS virtual 1 ; Mode of screen, [3:0] - VGA mode.
MMCFGVAL: DS virtual 1 ; Current memory model value.
HLSAVE: DS virtual 2 ; Storage for HL during bank switch manipulation.
AFSAVE: DS virtual 2 ; Storage for AF during bank switch manipulation.
FNADDR: DS virtual 2 ; Function to be called address.
TMPADR: DS virtual 2 ; TEMPORARY ADDRESS STORAGE
TMPSIZE: DS virtual 2 ; TEMPORARY SIZE
TMPCNT: DS virtual 2 ; TEMPORARY COUNTER
TMPLINECNT: DS virtual 2 ; Temporary counter for displayed lines.
TMPSTACKP: DS virtual 2 ; Temporary stack pointer save.
DUMPADDR: DS virtual 2 ; Address used by the D(ump) command so that calls without parameters go onto the next block.
CMTLOLOAD: DS virtual 1 ; Flag to indicate that a tape program is loaded into hi memory then shifted to low memory after ROM pageout.
CMTCOPY: DS virtual 1 ; Flag to indicate that a CMT copy operation is taking place.
CMTAUTOEXEC: DS virtual 1 ; Auto execution flag, run CMT program when loaded if flag clear.
DTADRSTORE: DS virtual 2 ; Backup for load address if actual load shifts to lo memory or to 0x1200 for copy.
SDCOPY: DS virtual 1 ; Flag to indicate an SD copy is taking place, either CMT->SD or SD->CMT.
RESULT: DS virtual 1 ; Result variable needed for interbank calls when a result is needed.
SDAUTOEXEC: DS virtual 1 ; Flag to indicate if a loaded file should be automatically executed.
FDCCMD: DS virtual 1 ; Floppy disk command storage.
MOTON: DS virtual 1 ; Motor on flag.
TRK0FD1: DS virtual 1 ; Floppy Disk 1 track 0 indicator.
TRK0FD2: DS virtual 1 ; Floppy Disk 2 track 0 indicator.
TRK0FD3: DS virtual 1 ; Floppy Disk 3 track 0 indicator.
TRK0FD4: DS virtual 1 ; Floppy Disk 4 track 0 indicator.
RETRIES: DS virtual 1 ; Retries count for a command.
BPARA: DS virtual 1
CMTINACTIVE: DS virtual 1 ; Flag to indicate if the CMT is inactive (1)/SD active (0) for the CMT wrapper handlers.
CMTFILENO: DS virtual 1 ; Sequential file access file number. Used when no filename is given, uses the directory entry number for the set wildcard,
HWMODEL: DS virtual 1 ; Model of machine to tailor code execution
CMTSAMPLECNT: DS virtual 1 ; Delay count for bit sampling.
CMTDLY1CNTM: DS virtual 1 ; Short pulse delay count MARK
CMTDLY1CNTS: DS virtual 1 ; Short pulse delay count SPACE
CMTDLY2CNTM: DS virtual 1 ; Long pulse delay count MARK
CMTDLY2CNTS: DS virtual 1 ; Long pulse delay count SPACE
DS virtual (TZVARMEM + TZVARSIZE) - $ ; Top of variable area downwards is used as the working stack, SA1510 space isnt used.
TZSTACK: EQU TZVARMEM + TZVARSIZE

View File

@@ -0,0 +1,8 @@
; Configurable parameters.
COLW: EQU 40 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
MODE80C:EQU 0 ; Monitor is being built for an 80 column display.
MODE2K: EQU 1 ; Monitor is being built for an MZ-2000 machine.
INCLUDE "1z-013a.asm"

View File

@@ -0,0 +1,8 @@
; Configurable parameters.
COLW: EQU 40 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
MODE80C:EQU 0 ; Monitor is being built for an 80 column display.
MODE2K: EQU 0 ; Monitor is being built for an MZ-2000 machine.
INCLUDE "1z-013a-km.asm"

View File

@@ -0,0 +1,8 @@
; Configurable parameters.
COLW: EQU 40 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
MODE80C:EQU 0 ; Monitor is being built for an 80 column display.
MODE2K: EQU 0 ; Monitor is being built for an MZ-2000 machine.
INCLUDE "1z-013a.asm"

View File

@@ -0,0 +1,8 @@
; Configurable parameters.
COLW: EQU 80 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
MODE80C:EQU 1 ; Monitor is being built for an 80 column display.
MODE2K: EQU 0 ; Monitor is being built for an MZ-2000 machine.
INCLUDE "1z-013a-km.asm"

View File

@@ -0,0 +1,8 @@
; Configurable parameters.
COLW: EQU 80 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
MODE80C:EQU 1 ; Monitor is being built for an 80 column display.
MODE2K: EQU 0 ; Monitor is being built for an MZ-2000 machine.
INCLUDE "1z-013a.asm"

View File

@@ -0,0 +1,9 @@
; Configurable parameters.
COLW: EQU 80 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
SCRLW: EQU COLW / 8 ; Number of 8 byte regions in a line for hardware scroll.
MODE80C:EQU 1
KUMA: EQU 0
INCLUDE "sa1510.asm"

View File

@@ -0,0 +1,9 @@
; Configurable parameters.
COLW: EQU 80 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
SCRLW: EQU COLW / 8 ; Number of 8 byte regions in a line for hardware scroll.
MODE80C:EQU 0
KUMA: EQU 1
INCLUDE "sa1510.asm"

View File

@@ -0,0 +1,9 @@
; Configurable parameters.
COLW: EQU 40 ; Width of the display screen (ie. columns).
ROW: EQU 25 ; Number of rows on display screen.
SCRNSZ: EQU COLW * ROW ; Total size, in bytes, of the screen display area.
SCRLW: EQU COLW / 8 ; Number of 8 byte regions in a line for hardware scroll.
MODE80C:EQU 0
KUMA: EQU 0
INCLUDE "sa1510.asm"

9699
software/asm/msbasic.asm Normal file

File diff suppressed because it is too large Load Diff

617
software/asm/mz-1e05.asm Normal file
View File

@@ -0,0 +1,617 @@
; V1.10
;
; To compile use:
;
; AS80 [1.31] - Assembler for 8080/8085/Z80 microprocessor.
;
; Available from:
; - http://www.falstaff.demon.co.uk/cross.html
; - ftp://ftp.simtel.net/pub/simtelnet/msdos/crossasm/as80_131.zip
; - and many Simtel mirrors.
;
; as80 -i -l -n -x2 -v -z mz-1e05.asm
;
;----< MFM Minifloppy control >----
;
;
; Call condition
;
; Case of disk initialize
; Drive N = IX+0 (0 - 3)
;
;
; Case of sequential read & write
; Drive N = IX+0 (0 - 3)
;
; Sector addrs = IX+1,2 (0 - $045F) H C S
; (0 - 1119) -> 70 x 16 sectors -> 2 x 35 x 16
; Byte size = IX+3,4
; Address = IX+5,6
; Next track = IX+7
; Next sector = IX+8
; Start track = IX+9
; Start sector = IX+10
;
;
; I/O Port address
;
CR EQU $D8 ; CommandRegister
TR EQU $D9 ; TrackRegister
SCR EQU $DA ; SeCtorRegister
DR EQU $DB ; DataRegister
DM EQU $DC ; DriveMotor
HS EQU $DD ; HeadSelect
TIMST EQU $0033
;
; Subroutine work
;
BPRO EQU $CF00
BUF EQU $11A3
BPARA EQU BPRO - 23 ; BootPARAmeter
CMD EQU BPARA + 11 ; CoMmanD
MTFG EQU CMD + 1 ; MoTorFlaG
CLBF0 EQU MTFG + 1
CLBF1 EQU CLBF0 + 1
CLBF2 EQU CLBF1 + 1
CLBF3 EQU CLBF2 + 1
VRFCNT EQU CLBF3 + 1 ; VeRiFyCouNT
STAFG EQU VRFCNT + 1 ; STAtusFlaG
;
;
;--------< Ercode map >--------
;
; 50 : Not ready
; 41 : Data error
; Track 80 err
; Write protect err
; Seek err
; CRC err
; Lost data
; 54 : Unformat
; Recode not found
; 56 : Invalid data
;
;
ORG $F000
MZ_1E05:
NOP
LD HL,$00AD
JR L_F007
FDX:
EX (SP),HL
L_F007:
LD (BPARA + 21),HL
XOR A
LD DE,0
CALL TIMST
CALL FDCC ; FD i/o check
JP NZ,NOTIO
LD DE,BPARA ; destination address
LD HL,BOOT ; source address
LD BC,11 ; 11 bytes
LDIR ; copy
SJP:
LD IX,BPARA
CALL BREAD ; read from drive 0, sector 0,
;
LD HL,BPRO ; compare this address
LD DE,IPLMC ; with the IPL MasterCode
LD B,7 ; this are 7 bytes : 3,'IPLPRO'
MCHECK:
LD C,(HL)
LD A,(DE)
CP C
JP NZ,MASTE ; not equal than MasterError
INC HL
INC DE
DJNZ MCHECK
; else Master was found
LD DE,IPLM0 ; 'IPL IS LOADING'
RST $18
LD DE,BPRO + 7 ; NAME
RST $18
LD HL,(BPRO + $16) ; TARGETADDRESS from BootBlock
LD A,H
OR L
JR NZ,L_F051 ; if it is != 0 than normal file
LD HL,(BPRO + $18) ; TARGETADDRESS from BootBlock
LD A,H
OR L
JR Z,L_F057 ; if it is also 0 than ROM replace file
L_F051:
XOR A ; else normal file,
LD HL,(BPRO + $18) ; TARGETADDRESS from BootBlock
JR L_F05C
L_F057:
LD A,$FF ; target is at $0000, bankswitching is needed
LD HL,$1200 ; for now use temporary buffer at $1200
L_F05C:
LD ($CEFD),A
LD (IX + 5),L ; set the TargetAddress
LD (IX + 6),H
LD HL,(BPRO + $14) ; BYTE SIZE from BootBlock
LD (IX + 3),L
LD (IX + 4),H
LD HL,(BPRO + $1E) ; START SECTOR from BootBlock
LD (IX + 1),L
LD (IX + 2),H
;
CALL BREAD
CALL MOFF
LD A,($CEFD)
CP $FF
JR NZ,L_F093
OUT ($E0),A
LD HL,$1200 ; SourceAddress
LD DE,(BPRO + $16) ; TargetAddress
LD BC,(BPRO + $14) ; ByteCounter
LDIR ; copy
L_F093:
LD BC,$0200 ; Default code
LD HL,(BPRO + $18) ; TARGET/EXECUTION ADDRESS from BootBlock
JP (HL)
MASTE:
CALL MOFF
LD DE,ERRM1 ; 'NOT MASTER'
JR ERRTR1
ERRTRT:
CP 50
NOTIO:
LD DE,IPLM3 ; 'MAKE READY FD'
JR Z,ERRTR1
LD DE,ERRM0 ; 'FD:LOADING ERROR'
ERRTR1:
CALL $0009
RST $18
LD SP,$10EE
LD HL,(BPARA + 21)
EX (SP),HL
RET
;
;
; PARAMETER SETTING
;
IPLMC:
DB $03 ; IPL MASTER FLAG
DB 'IPLPRO'
BOOT:
DB $00 ; DRIVE NO.
DW $0000 ; SECTOR ADDR.
DW $0100 ; IFM BYTE SIZE
DW BPRO ; IFM LOADING ADDR.
DW $0000 ; IX+7,8 (track 0, sector 0)
ERRM1:
DB 'FD:NOT MASTER',$0D
IPLM0:
DB 'IPL IS LOADING ',$0D
IPLM3:
DB 'MAKE READY FD',$0D
ERRM0:
DB 'FD:LOADING ERROR',$0D
FDCC:
LD A,$A5
LD B,A
OUT (TR),A
CALL DLY80U
IN A,(TR)
CP B
RET
L_F111:
DB $00, $00
;
;
; READY CHECK
;
READY:
LD A,(MTFG)
RRCA
CALL NC,MTON
LD A,(IX + 0) ; DRIVE NO SET
OR $84
OUT (DM),A ; DRIVE SELECT MOTON
XOR A
LD (CMD),A
CALL DLY60M
LD HL,0
REDY0:
DEC HL
LD A,H
OR L
JR Z,REDY1
IN A,(CR) ; STATUS GET
CPL
RLCA
JR C,REDY0
LD C,(IX + 0)
LD HL,CLBF0
LD B,$00
ADD HL,BC
BIT 0,(HL)
JR NZ,REDY2
CALL RCLB
SET 0,(HL)
REDY2:
RET
REDY1:
LD A,$32
JP ERJMP
;
;
; MOTOR ON
;
MTON:
LD A,$80
OUT (DM),A
LD B,16
MTD1:
CALL DLY60M
DJNZ MTD1
LD A,1
LD (MTFG),A
RET
;
;
; SEEK TREATMENT
;
SEEK:
LD A,$1B ; 1x = SEEK,
CALL CMDOT1 ; load head, no verify, max stepping rate
AND $99
RET
;
;
; MOTOR OFF
;
MOFF:
PUSH AF
CALL DLY1M ; 1000 US DELAY
XOR A
OUT (DM),A
LD (CLBF0),A
LD (CLBF1),A
LD (CLBF2),A
LD (CLBF3),A
LD (MTFG),A
POP AF
RET
;
;
; RECALIBRATION
;
RCLB:
LD A,$0B ; 0x = RESTORE (seek track 0)
CALL CMDOT1 ; load head, no verify, max stepping rate
AND $85
XOR $04
RET Z
L_F189:
JP ERROR
;
;
; COMMAND OUT ROUTINE
;
CMDOT1:
LD (CMD),A
CPL
OUT (CR),A
CALL BSYON
CALL DLY60M
IN A,(CR)
CPL
LD (STAFG),A
RET
;
;
; BUSY AND WAIT
;
BSYON:
PUSH DE
PUSH HL
CALL BSY0
BSYON2:
LD HL,$0000
BSYON0:
DEC HL
LD A,H
OR L
JR Z,BSYON1
IN A,(CR)
RRCA
JR NC,BSYON0
POP HL
POP DE
RET
;
BSYON1:
DEC E
JR NZ,BSYON2
BSYONE:
LD A,$29
POP HL
POP DE
JP ERJMP
;
BSYOFF:
PUSH DE
PUSH HL
CALL BSY0
BSYOF2:
LD HL,$0000
BSYOF0:
DEC HL
LD A,H
OR L
JR Z,BSYOF1
IN A,(CR) ; Status Register
RRCA
JR C,BSYOF0
POP HL
POP DE
RET
;
BSYOF1:
DEC E
JR NZ,BSYOF2
JR BSYONE
;
BSY0:
CALL DLY80U
LD E,$07
RET
;
;
; SEQUENTIAL READ
;
BREAD:
CALL CNVRT
CALL PARST1 ; HL = IX + 5,6 (TargetAddress)
RE8:
CALL SIDST
CALL SEEK
JP NZ,ERJMP
CALL PARST2 ; C = DataRegister
DI ; disable interrupts
LD A,$94 ; 9x = READ SECTOR, multiple records
CALL CMDOT2 ; compare for side 0, 15ms delay,
RE6: ; disable side select compare
LD B,0 ; ByteCounter = 0, to load 256 bytes of the sector
RE4:
IN A,(CR)
RRCA
JR C,RE3
RRCA
JR C,RE4
INI ; (HL) = in(C), B = B - 1 , HL = HL + 1
JR NZ,RE4
INC (IX + 8) ; NextSector = NextSector + 1
LD A,(IX + 8)
CP $11 ; if NextSector = 17
JR Z,L_F213 ; than end
DEC D ; else SectorCounter = SectorCounter - 1
JR NZ,RE6 ; if SectorCounter = 0
JR L_F214 ; than end
L_F213:
DEC D
L_F214:
CALL INTER
RE3:
EI ; enable interrupts
IN A,(CR)
CPL
LD (STAFG),A
AND $FF
JR NZ,ERROR
CALL ADJ ; adjust sector and track
JP Z,REND
LD A,(IX + 7) ; track
JR RE8
REND:
LD A,$80
OUT (DM),A ; motor on
RET
;
;
; PARAMETER SET
;
;
PARST1:
CALL READY
LD D,(IX + 4) ; D = bytes to read (highbyte) (256 bytes)
LD A,(IX + 3) ; A = bytes to read (lowbyte)
OR A ; if A = 0
JR Z,L_F23F ; than it's ok
INC D ; else read 256 bytes more (1 sector)
L_F23F:
LD A,(IX + 10) ; NextSector = StartSector
LD (IX + 8),A
LD A,(IX + 9) ; NextTrack = StartTrack
LD (IX + 7),A
LD L,(IX + 5) ; HL = TargetAddress
LD H,(IX + 6)
RET
;
;
; SIZE SEEK SET
;
SIDST:
SRL A
CPL
OUT (DR),A
JR NC,L_F25D ; NC than Head 0
LD A,1 ; else Head 1
JR L_F25E
L_F25D:
XOR A
L_F25E:
CPL
OUT (HS),A ; set HeadSelect
RET
;
;
; TRACK & SECTOR SET
;
PARST2:
LD C,DR
LD A,(IX + 7) ; A = NextTrack
SRL A
CPL
OUT (TR),A
LD A,(IX + 8) ; A = NextSector
CPL
OUT (SCR),A
RET
;
;
; ADJUST SECT & TRACK
;
ADJ:
LD A,(IX + 8) ; A = NextSector
CP 17 ; if NextSector = 17
JR NZ,L_F282 ; than the border is not reached
LD A,$01 ; else
LD (IX + 8),A ; NextSector = 1
INC (IX + 7) ; NextTrack = NextTrack + 1
L_F282:
LD A,D
OR A
RET
;
;
; COMMAND OUT & WAIT
;
CMDOT2:
LD (CMD),A
CPL
OUT (CR),A
CALL BSYOFF
RET
;
;
; FORCE INTERRUPT
;
INTER:
LD A,$D8
CPL
OUT (CR),A
CALL BSYON
RET
;
;
; STATUS CHECK
;
ERROR:
LD A,(CMD)
CP $0B ; Restore (seek track 0)
JR Z,ERCK1
CP $1B ; Seek
JR Z,ERCK1
CP $F4 ; Write track
JR Z,ERCK1
LD A,(STAFG)
BIT 7,A
JR NZ,ERRET
BIT 6,A
JR NZ,ERRET1
BIT 4,A
LD A,54
JR NZ,ERJMP
JR ERRET1
ERCK1:
LD A,(STAFG)
BIT 7,A
JR NZ,ERRET
ERRET1:
LD A,41
JR ERJMP
ERRET:
LD A,50
ERJMP:
CALL MOFF
JP ERRTRT
;
;
; SECTOR TO TRACK & SECTOR CONVERT
;
CNVRT:
LD B,0 ; TrackCounter = 0
LD DE,16 ; 16 sectors per track
LD L,(IX + 1) ; HL = SectorAddress
LD H,(IX + 2)
XOR A
TRANS0:
SBC HL,DE ; SectorAddress - SectorPerTrack
JR C,TRANS1 ; if < 0 than ready
INC B ; else TrackCounter = TrackCounter + 1
JR TRANS0 ; next try
TRANS1:
ADD HL,DE ; undo the last substraction
LD H,B
INC L ; adjust sector (sector is 1..16 and not 0..15)
LD (IX + 9),H ; set StartTrack
LD (IX + 10),L ; set StartSector
RET
;
;
; TIME DELAY ( 1m & 60m & 80u )
;
DLY80U:
PUSH DE
LD DE,15
JP DLYT
DLY1M:
PUSH DE
LD DE,160
JP DLYT
DLY60M:
PUSH DE
LD DE,8230
DLYT:
DEC DE
LD A,E
OR D
JR NZ,DLYT
POP DE
RET
ORG $FFF0
DB ' 84.03.14 V1.0A'

1739
software/asm/mz2000_ipl.asm Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
; Configurable parameters.
;BUILDVERSION EQU 0 ; Build original IPL ROM.
;BUILDVERSION EQU 1 ; Build enhanced tranZPUter IPL ROM.
BUILDVERSION EQU 2 ; Build enhanced for FusionX IPL ROM.
INCLUDE "mz2000_ipl.asm"

View File

@@ -0,0 +1,5 @@
; Configurable parameters.
BUILDVERSION EQU 0 ; Build original IPL ROM.
;BUILDVERSION EQU 1 ; Build enhanced tranZPUter IPL ROM.
INCLUDE "mz2000_ipl.asm"

View File

@@ -0,0 +1,5 @@
; Configurable parameters.
;BUILDVERSION EQU 0 ; Build original IPL ROM.
BUILDVERSION EQU 1 ; Build enhanced tranZPUter IPL ROM.
INCLUDE "mz2000_ipl.asm"

View File

@@ -0,0 +1,4 @@
; Configurable parameters.
BUILDVERSION EQU 2 ; Build enhanced tranZPUter IPL ROM.
INCLUDE "1Z001M.asm"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1613
software/asm/mz800_iocs.asm Normal file

File diff suppressed because it is too large Load Diff

372
software/asm/mz80afi.asm Normal file
View File

@@ -0,0 +1,372 @@
; Disassembly of the file "D:\MZ80AFI.BIN"
;
; CPU Type: Z80
;
; Using the opcode map file "D:\DZ80-INI.MAP"
; ; Created with dZ80 2.0
;
; on Thursday, 06 of February 2020 at 01:38 PM
;
i ; Bring in additional resources.
INCLUDE "tzfs_definitions.asm"
INCLUDE "tzfs_mondef.asm"
INCLUDE "macros.asm"
;======================================
;
; Floppy Disk Interface
;
;======================================
ORG 0E800H
FLOPPY: NOP
LD DE,01008H
LD HL,PRMBLK
LD BC,0000BH
LDIR
CALL L0151
L000F: CALL NL
LD DE,BOOTDRV
CALL MSG
LD DE,011A3H
CALL GETL
LD A,(DE)
CP 01BH
JP Z,SS
LD HL,0000CH
ADD HL,DE
LD A,(HL)
CP 00DH
JR Z,L003A ; (+00dh)
CALL 03F9H
JR C,L000F ; (-023h)
DEC A
CP 004H
JR NC,L000F ; (-028h)
LD (01008H),A
L003A: LD IX,01008H
CALL L01BA
LD HL,0CE00H
LD DE,DSKID
LD B,007H
L0049: LD C,(HL)
LD A,(DE)
CP C
JP NZ,L008C
INC HL
INC DE
DJNZ L0049 ; (-00ah)
CALL NL
LD DE,IPLLOAD
CALL MSG
LD DE,0CE07H
CALL MSG
LD HL,(0CE16H)
LD (IX+005H),L
LD (IX+006H),H
LD HL,(0CE14H)
LD (IX+003H),L
LD (IX+004H),H
LD HL,(0CE1EH)
LD (IX+001H),L
LD (IX+002H),H
CALL L01BA
CALL L0151
LD HL,(0CE18H)
JP (HL)
L0087: LD DE,LOADERR
JR L008F ; (+003h)
L008C: LD DE,DSKNOTMST
L008F: CALL NL
CALL MSG
CALL NL
LD DE,DSKDAT
CALL MELDY
JP SS
BOOTDRV: DB "BOOY DRIVE ?", 00DH
LOADERR: DB "LOADING ERROR", 00DH
IPLLOAD: DB "IPL IS LOADING ", 00DH
DSKID: DB 002H, "IPLPRO"
DSKDAT: DB "A0", 0D7H, "ARA", 0D7H, "AR", 00DH
PRMBLK: DB 000H, 000H, 000H, 000H, 001H, 000H, 0CEH, 000H, 000H, 000H, 000H
DSKNOTMST: DB "THIS DISKETTE IS NOT MASTER", 00Dh
L0104: LD A,(01001H)
RRCA
CALL NC,L0138
LD A,(IX+000H)
OR 084H
OUT (0DCH),A
XOR A
LD (01000H),A
LD HL,00000H
L0119: DEC HL
LD A,H
OR L
JP Z,L029D
IN A,(0D8H)
CPL
RLCA
JR C,L0119 ; (-00ch)
LD C,(IX+000H)
LD HL,01002H
LD B,000H
ADD HL,BC
BIT 0,(HL)
JR NZ,L0137 ; (+005h)
CALL L0164
SET 0,(HL)
L0137: RET
L0138: LD A,080H
OUT (0DCH),A
LD B,010H
L013E: CALL L02C7
DJNZ L013E ; (-005h)
LD A,001H
LD (01001H),A
RET
L0149: LD A,01BH
CALL L0171
AND 099H
RET
L0151: XOR A
OUT (0DCH),A
LD (01002H),A
LD (01003H),A
LD (01004H),A
LD (01005H),A
LD (01001H),A
RET
L0164: LD A,00BH
CALL L0171
AND 085H
XOR 004H
RET Z
JP L029D
L0171: LD (01000H),A
CPL
OUT (0D8H),A
CALL L017E
IN A,(0D8H)
CPL
RET
L017E: PUSH DE
PUSH HL
CALL L02C0
LD E,007H
L0185: LD HL,00000H
L0188: DEC HL
LD A,H
OR L
JR Z,L0196 ; (+009h)
IN A,(0D8H)
CPL
RRCA
JR C,L0188 ; (-00bh)
POP HL
POP DE
RET
L0196: DEC E
JR NZ,L0185 ; (-014h)
JP L029D
L019C: PUSH DE
PUSH HL
CALL L02C0
LD E,007H
L01A3: LD HL,00000H
L01A6: DEC HL
LD A,H
OR L
JR Z,L01B4 ; (+009h)
IN A,(0D8H)
CPL
RRCA
JR NC,L01A6 ; (-00bh)
POP HL
POP DE
RET
L01B4: DEC E
JR NZ,L01A3 ; (-014h)
JP L029D
L01BA: CALL L0220
L01BD: CALL L0229
L01C0: CALL L0249
CALL L0149
JR NZ,L0216 ; (+04eh)
CALL L0259
PUSH IX
LD IX,L03FE
LD IY,L01DF
DI
LD A,094H
CALL L028A
L01DB: LD B,000H
JP (IX)
L01DF: INI
JP NZ,L03FE
POP IX
INC (IX+008H)
LD A,(IX+008H)
PUSH IX
LD IX,L03FE
CP 011H
JR Z,L01FB ; (+005h)
DEC D
JR NZ,L01DB ; (-01eh)
JR L01FC ; (+001h)
L01FB: DEC D
L01FC: CALL L0294
CALL L02D2
POP IX
IN A,(0D8H)
CPL
AND 0FFH
JR NZ,L0216 ; (+00bh)
CALL L0278
JP Z,L021B
LD A,(IX+007H)
JR L01C0 ; (-056h)
L0216: CALL L026A
JR L01BD ; (-05eh)
L021B: LD A,080H
OUT (0DCH),A
RET
L0220: CALL L02A3
LD A,00AH
LD (01006H),A
RET
L0229: CALL L0104
LD D,(IX+004H)
LD A,(IX+003H)
OR A
JR Z,L0236 ; (+001h)
INC D
L0236: LD A,(IX+00AH)
LD (IX+008H),A
LD A,(IX+009H)
LD (IX+007H),A
LD L,(IX+005H)
LD H,(IX+006H)
RET
L0249: SRL A
CPL
OUT (0DBH),A
JR NC,L0254 ; (+004h)
LD A,001H
JR L0255 ; (+001h)
L0254: XOR A
L0255: CPL
OUT (0DDH),A
RET
L0259: LD C,0DBH
LD A,(IX+007H)
SRL A
CPL
OUT (0D9H),A
LD A,(IX+008H)
CPL
OUT (0DAH),A
RET
L026A: LD A,(01006H)
DEC A
LD (01006H),A
JP Z,L029D
CALL L0164
RET
L0278: LD A,(IX+008H)
CP 011H
JR NZ,L0287 ; (+008h)
LD A,001H
LD (IX+008H),A
INC (IX+007H)
L0287: LD A,D
OR A
RET
L028A: LD (01000H),A
CPL
OUT (0D8H),A
CALL L019C
RET
L0294: LD A,0D8H
CPL
OUT (0D8H),A
CALL L017E
RET
L029D: CALL L0151
JP L0087
L02A3: LD B,000H
LD DE,00010H
LD L,(IX+001H)
LD H,(IX+002H)
XOR A
L02AF: SBC HL,DE
JR C,L02B6 ; (+003h)
INC B
JR L02AF ; (-007h)
L02B6: ADD HL,DE
LD H,B
INC L
LD (IX+009H),H
LD (IX+00AH),L
RET
L02C0: PUSH DE
LD DE,00007H
JP L02CB
L02C7: PUSH DE
LD DE,01013H
L02CB: DEC DE
LD A,E
OR D
JR NZ,L02CB ; (-005h)
POP DE
RET
L02D2: PUSH AF
LD A,(0119CH)
CP 0F0H
JR NZ,L02DB ; (+001h)
EI
L02DB: POP AF
RET
ALIGN 0EBFDh
DB 0FFh
L03FE: JP (IY)
;DB 0DDH
; DB 0E9H
; Ensure we fill the entire 1K by padding with FF's.
ALIGN 0EFFDh
DB 0FFh
LF7FE: DB 0fDH
DB 0E9H

904
software/asm/mz80b_ipl.asm Normal file
View File

@@ -0,0 +1,904 @@
ORG 0000H
;****************************************************************
;
; Personal Computer
; MZ-80B
;
; Initial Program Loader
;****************************************************************
;
JR START
;
; NST RESET
;
NST: LD A,03H
OUT (PPICTL),A ;Set PC1 NST=1
;
START: LD A,82H ;8255 A=OUT B=IN C=OUT
OUT (PPICTL),A
LD A,0FH ;PIO A=OUT
OUT (PIOCTLA),A
LD A,0CFH ;PIO B=IN
OUT (PIOCTLB),A
LD A,0FFH
OUT (PIOCTLB),A
LD A,58H ;BST=1 NST=0 OPEN=1 WRITE=1
OUT (PPIC),A
LD A,12H
OUT (PPIA),A
XOR A
OUT (GRPHCTL),A ;Set Graphics VRAM to default, input to GRPH I, no output.
LD SP,0FFE0H
LD HL,0D000H
LD A,0B3H
OUT (PIOA),A
CLEAR: LD (HL),00H ;DISPLAY CLEAR
INC HL
LD A,H
OR L
JR NZ,CLEAR
LD A,13H
OUT (PIOA),A
XOR A
LD (DRINO),A
LD (MTFG),A
KEYIN: CALL KEYS1
BIT 3,A ;C - Cassette.
JR Z,CMT
BIT 0,A ;/ - Boot external rom.
JP Z,EXROMT
JR NKIN ;No selection, so standard startup, try FDC then CMT.
;
KEYS1: LD B,14H ;Preserve A4-A7, set A4 to prevent all strobes low, the select line 5 (0-4).
KEYS: IN A,(PIOA)
AND 0F0H
OR B
OUT (PIOA),A
IN A,(PIOB) ;Read the strobed key.
RET
;
;
NKIN: CALL FDCC
JP Z,FD
JR CMT
;
FDCC: LD A,0A5H
LD B,A
OUT (0D9H),A
CALL DLY80U
IN A,(0D9H)
CP B
RET
;
; ;
; CMT CONTROL ;
; ;
;
CMT: CALL MSTOP
CALL DEL6
CALL KYEMES
CALL ?RDI
JR C,ST1
CALL LDMSG
LD HL,NAME
LD E,010H
LD C,010H
CALL DISP2
LD A,(ATRB)
CP 01H
JR NZ,MISMCH
CALL ?RDD
ST1: PUSH AF
CALL DEL6
CALL REW
POP AF
JP C,TRYAG
JP NST
;
MISMCH: LD HL,MES16
LD E,0AH
LD C,0FH
CALL DISP
CALL MSTOP
SCF
JR ST1
;
;READ INFORMATION
; CF=1:ERROR
RDINF:
?RDI: DI
LD D,04H
LD BC,0080H
LD HL,IBUFE
RD1: CALL MOTOR
JR C,STPEIR
CALL TMARK
JR C,STPEIR
CALL RTAPE
JR C,STPEIR
RET2S: BIT 3,D
JR Z,EIRTN
STPEIR: CALL MSTOP
EIRTN: EI
RET
;
;
;READ DATA
RDDAT:
?RDD: DI
LD D,08H
LD BC,(SIZE)
LD HL,8000H
JR RD1
;
;
;READ TAPE
; BC=SIZE
; DE=LOAD ADDRSS
RTAPE: PUSH DE
PUSH BC
PUSH HL
LD H,02H
RTP2: CALL SPDIN
JR C,TRTN1 ;BREAK
JR Z,RTP2
LD D,H
LD HL,0000H
LD (SUMDT),HL
POP HL
POP BC
PUSH BC
PUSH HL
RTP3: CALL RBYTE
JR C,TRTN1
LD (HL),A
INC HL
DEC BC
LD A,B
OR C
JR NZ,RTP3
LD HL,(SUMDT)
CALL RBYTE
JR C,TRTN1
LD E,A
CALL RBYTE
JR C,TRTN1
CP L
JR NZ,RTP5
LD A,E
CP H
JR Z,TRTN1
RTP5: DEC D
JR Z,RTP6
LD H,D
JR RTP2
RTP6: CALL BOOTER
SCF
TRTN1: POP HL
POP BC
POP DE
RET
;EDGE
EDGE: IN A,(PPIB)
CPL
RLCA
RET C ;BREAK
RLCA
JR NC,EDGE ;WAIT ON LOW
EDGE1: IN A,(PPIB)
CPL
RLCA
RET C ;BREAK
RLCA
JR C,EDGE1 ;WAIT ON HIGH
RET
; 1 BYTE READ
; DATA=A
; SUMDT STORE
RBYTE: PUSH HL
LD HL,0800H ; 8 BITS
RBY1: CALL SPDIN
JR C,RBY3 ;BREAK
JR Z,RBY2 ;BIT=0
PUSH HL
LD HL,(SUMDT) ;CHECKSUM
INC HL
LD (SUMDT),HL
POP HL
SCF
RBY2: RL L
DEC H
JR NZ,RBY1
CALL EDGE
LD A,L
RBY3: POP HL
RET
;TAPE MARK DETECT
; E=L:INFORMATION
; E=S:DATA
TMARK: PUSH HL
LD HL,1414H
BIT 3,D
JR NZ,TM0
ADD HL,HL
TM0: LD (TMCNT),HL
TM1: LD HL,(TMCNT)
TM2: CALL SPDIN
JR C,RBY3
JR Z,TM1
DEC H
JR NZ,TM2
TM3: CALL SPDIN
JR C,RBY3
JR NZ,TM1
DEC L
JR NZ,TM3
CALL EDGE
JR RBY3
;READ 1 BIT
SPDIN: CALL EDGE ;WAIT ON HIGH
RET C ;BREAK
CALL DLY2
IN A,(PPIB) ;READ BIT
AND 40H
RET
;
;
;MOTOR ON
MOTOR: PUSH DE
PUSH BC
PUSH HL
IN A,(PPIB)
AND 20H
JR Z,MOTRD
LD HL,MES6
LD E,0AH
LD C,0EH
CALL DISP
CALL OPEN
MOT1: IN A,(PIOB)
CPL
RLCA
JR C,MOTR
IN A,(PPIB)
AND 20H
JR NZ,MOT1
CALL KYEMES
CALL DEL1M
MOTRD: CALL PLAY
MOTR: POP HL
POP BC
POP DE
RET
;
;
;MOTOR STOP
MSTOP: LD A,0DH
OUT (PPICTL),A ;Set PC6 - READ MODE
LD A,1AH
OUT (PPIA),A
CALL DEL6
JR BLK3
;EJECT
OPEN: LD A,08H ;Reset PC4 - EJECT activate
OUT (PPICTL),A
CALL DEL6
LD A,09H
OUT (PPICTL),A ;Set PC4 - Deactivate EJECT
RET
;
;
KYEMES: LD HL,MES3
LD E,04H
LD C,1CH
CALL DISP
RET
;
;PLAY
PLAY: CALL FR
CALL DEL6
LD A,16H
OUT (PPIA),A
JR BLK3
BLK1: CALL DEL6
CALL BLK3
LD A,13H
BLK2: OUT (PPIA),A
BLK3: LD A,12H
OUT (PPIA),A
RET
;
;
FR: LD A,12H
FR1: OUT (PPIA),A
CALL DEL6
LD A,0BH
OUT (PPICTL),A ;Set PC5
CALL DEL6
LD A,0AH
OUT (PPICTL),A ;Reset PC5
RET
RRW: LD A,010H
JR FR1
;REWIND
REW: CALL RRW
JR BLK1
;
;TIMING DEL
DM1: PUSH AF
L0211: XOR A
L0212: DEC A
JR NZ,L0212
DEC BC
LD A,B
OR C
JR NZ,L0211
POP AF
POP BC
RET
DEL6: PUSH BC
LD BC,00E9H ;233D
JR DM1
DEL1M: PUSH BC
LD BC,060FH ;1551D
JR DM1
;
;TAPE DELAY TIMING
;
;
; CALL - 17 T-states
; LD - 7 T-states
; DEC - 4 T-states
; JP cc- 10 T-states
; RET - 10 T-states
; 17 + 7 + ((4+10)*49) + 10 = 720 * 1/4000000 = 180uS
DLY2: LD A,31H
L022B: DEC A
JP NZ,L022B
RET
;
;
;
LDMSG: LD HL,MES1
LD E,00H
LD C,0EH
JR DISP
;
DISP2: LD A,93H
OUT (PIOA),A
JR DISP1
;
BOOTER: LD HL,MES8
LD E,0AH
LD C,0DH
;
DISP: LD A,93H
OUT (PIOA),A
EXX
LD HL,0D000H
DISP3: LD (HL),00H
INC HL
LD A,H
OR L
JR NZ,DISP3
EXX
DISP1: XOR A
LD B,A
LD D,0D0H
LDIR
LD A,13H
OUT (PIOA),A
RET
;
;
MES1: DB "IPL is loading"
MES3: DB "IPL is looking for a program"
MES6: DB "Make ready CMT"
MES8: DB "Loading error"
MES9: DB "Make ready FD"
MES10: DB "Press F or C"
MES11: DB "F:Floppy diskette"
MES12: DB "C:Cassette tape"
MES13: DB "Drive No? (1-4)"
MES14: DB "This diskette is not master"
MES15: DB "Pressing S key starts the CMT"
MES16: DB "File mode error"
;
IPLMC: DB 01H
DB "IPLPRO"
;
;
;FD
FD: LD IX,IBADR1
XOR A
LD (0CF1EH),A
LD (0CF1FH),A
LD IY,0FFE0H
LD HL,0100H
LD (IY+2),L
LD (IY+3),H
CALL BREAD ;INFORMATION INPUT
LD HL,0CF00H ;MASTER CHECK
LD DE,IPLMC
LD B,06H
MCHECK: LD C,(HL)
LD A,(DE)
CP C
JP NZ,NMASTE
INC HL
INC DE
DJNZ MCHECK
CALL LDMSG
LD HL,0CF07H
LD E,010H
LD C,0AH
CALL DISP2
LD IX,IBADR2
LD HL,(0CF14H)
LD (IY+2),L
LD (IY+3),H
CALL BREAD
CALL MOFF
JP NST
;
;
NODISK: LD HL,MES9
LD E,0AH
LD C,0DH
CALL DISP
JP ERR1
;
; READY CHECK
;
READY: LD A,(MTFG)
RRCA
CALL NC,MTON
LD A,(DRINO) ;DRIVE NO GET
OR 84H
OUT (DM),A ;DRIVE SELECT MOTON
XOR A
CALL DLY60M
LD HL,0000H
REDY0: DEC HL
LD A,H
OR L
JR Z,NODISK
IN A,(CR) ;STATUS GET
CPL
RLCA
JR C,REDY0
LD A,(DRINO)
LD C,A
LD HL,CLBF0
LD B,00H
ADD HL,BC
BIT 0,(HL)
RET NZ
CALL RCLB
SET 0,(HL)
RET
;
; MOTOR ON
;
MTON: LD A,80H
OUT (DM),A
LD B,0AH ;1SEC DELAY
MTD1: LD HL,3C19H
MTD2: DEC HL
LD A,L
OR H
JR NZ,MTD2
DJNZ MTD1
LD A,01H
LD (MTFG),A
RET
;
;SEEK TREATMENT
;
SEEK: LD A,1BH
CPL
OUT (CR),A
CALL BUSY
CALL DLY60M
IN A,(CR)
CPL
AND 99H
RET
;
;MOTOR OFF
;
MOFF: CALL DLY1M
XOR A
OUT (DM),A
LD (CLBF0),A
LD (CLBF1),A
LD (CLBF2),A
LD (CLBF3),A
LD (MTFG),A
RET
;
;RECALIBRATION
;
RCLB: PUSH HL
LD A,0BH
CPL
OUT (CR),A
CALL BUSY
CALL DLY60M
IN A,(CR)
CPL
AND 85H
XOR 04H
POP HL
RET Z
JP ERR
;
;BUSY AND WAIT
;
BUSY: PUSH DE
PUSH HL
CALL DLY80U
LD E,07H
BUSY2: LD HL,0000H
BUSY0: DEC HL
LD A,H
OR L
JR Z,BUSY1
IN A,(CR)
CPL
RRCA
JR C,BUSY0
POP HL
POP DE
RET
;
BUSY1: DEC E
JR NZ,BUSY2
JP ERR
;
;DATA CHECK
;
CONVRT: LD B,00H
LD DE,0010H
LD HL,(0CF1EH)
XOR A
TRANS: SBC HL,DE
JR C,TRANS1
INC B
JR TRANS
TRANS1: ADD HL,DE
LD H,B
INC L
LD (IY+4),H
LD (IY+5),L
DCHK: LD A,(DRINO)
CP 04H
JR NC,DTCK1
LD A,(IY+4)
CP 46H ;70D
JR NC,DTCK1
LD A,(IY+5)
OR A
JR Z,DTCK1
CP 11H ;17D
JR NC,DTCK1
LD A,(IY+2)
OR (IY+3)
RET NZ
DTCK1: JP ERR
;
;SEQUENTIAL READ
;
BREAD: DI
CALL CONVRT
LD A,0AH
LD (RETRY),A
READ1: CALL READY
LD D,(IY+3)
LD A,(IY+2)
OR A
JR Z,RE0
INC D
RE0: LD A,(IY+5)
LD (IY+1),A
LD A,(IY+4)
LD (IY+0),A
PUSH IX
POP HL
RE8: SRL A
CPL
OUT (DR),A
JR NC,RE1
LD A,01H
JR RE2
RE1: LD A,00H
RE2: CPL
OUT (HS),A
CALL SEEK
JR NZ,REE
LD C,0DBH
LD A,(IY+0)
SRL A
CPL
OUT (TR),A
LD A,(IY+1)
CPL
OUT (SCR),A
EXX
LD HL,RE3
PUSH HL
EXX
LD A,94H
CPL
OUT (CR),A
CALL WAIT
RE6: LD B,00H
RE4: IN A,(CR)
RRCA
RET C
RRCA
JR C,RE4
INI
JR NZ,RE4
INC (IY+1)
LD A,(IY+1)
CP 11H ;17D
JR Z,RETS
DEC D
JR NZ,RE6
JR RE5
RETS: DEC D
RE5: LD A,0D8H ;FORCE INTERRUPT
CPL
OUT (CR),A
CALL BUSY
RE3: IN A,(CR)
CPL
AND 0FFH
JR NZ,REE
EXX
POP HL
EXX
LD A,(IY+1)
CP 11H ;17D
JR NZ,REX
LD A,01H
LD (IY+1),A
INC (IY+0)
REX: LD A,D
OR A
JR NZ,RE7
LD A,80H
OUT (DM),A
RET
RE7: LD A,(IY+0)
JR RE8
REE: LD A,(RETRY)
DEC A
LD (RETRY),A
JR Z,ERR
CALL RCLB
JP READ1
;
; WAIT AND BUSY OFF
;
WAIT: PUSH DE
PUSH HL
CALL DLY80U
LD E,08H
WAIT2: LD HL,0000H
WAIT0: DEC HL
LD A,H
OR L
JR Z,WAIT1
IN A,(CR)
CPL
RRCA
JR NC,WAIT0
POP HL
POP DE
RET
WAIT1: DEC E
JR NZ,WAIT2
JR ERR
;
NMASTE: LD HL,MES14
LD E,07H
LD C,1BH ;27D
CALL DISP
JR ERR1
;
; ;
; ERRROR OR BREAK ;
; ;
;
ERR: CALL BOOTER
ERR1: CALL MOFF
TRYAG2: LD SP,0FFE0H
;
;TRYAG
;
TRYAG: CALL FDCC
JR NZ,TRYAG3
LD HL,MES10
LD E,5AH
LD C,0CH ;12D
CALL DISP2
LD E,0ABH
LD C,11H ;17D
CALL DISP2
LD E,0D3H
LD C,0FH ;15D
CALL DISP2
TRYAG1: CALL KEYS1
BIT 3,A
JP Z,CMT
BIT 6,A
JR Z,DNO
JR TRYAG1
DNO: LD HL,MES13 ;DRIVE NO SELECT
LD E,0AH
LD C,0FH
CALL DISP
DNO10: LD D,12H
CALL DNO0
JR NC,DNO3
LD D,18H
CALL DNO0
JR NC,DNO3
JR DNO10
DNO3: LD A,B
LD (DRINO),A
JP FD
;
TRYAG3: LD HL,MES15
LD E,54H
LD C,1DH ;29D
CALL DISP2
TRYAG4: LD B,06H
TRYAG5: CALL KEYS
BIT 3,A
JP Z,CMT
JR TRYAG5
;
DNO0: IN A,(PIOA)
AND 0F0H
OR D
OUT (PIOA),A
IN A,(PIOB)
LD B,00H
LD C,04H
RRCA
DNO1: RRCA
RET NC
INC B
DEC C
JR NZ,DNO1
RET
;
; TIME DELAY (1M &60M &80U )
;
DLY80U: PUSH DE
LD DE,000DH ;13D
JP DLYT
DLY1M: PUSH DE
LD DE,0082H ;130D
JP DLYT
DLY60M: PUSH DE
LD DE,1A2CH ;6700D
DLYT: DEC DE
LD A,E
OR D
JR NZ,DLYT
POP DE
RET
;
;
; ;
; INTRAM EXROM ;
; ;
;
EXROMT: LD HL,8000H
LD IX,EROM1
JR SEROMA
EROM1: IN A,(0F9H)
CP 00H
JP NZ,NKIN
LD IX,EROM2
ERMT1: JR SEROMA
EROM2: IN A,(0F9H)
LD (HL),A
INC HL
LD A,L
OR H
JR NZ,ERMT1
OUT (0F8H),A
JP NST
;
SEROMA: LD A,H
OUT (0F8H),A
LD A,L
OUT (0F9H),A
LD D,04H
SEROMD: DEC D
JR NZ,SEROMD
JP (IX)
; Align to ROM size.
DS 0800H - 1 - ($ + 0800H - 1) % 0800H, 0FFh
;----------------------------------------------------------
; Variables/Work area
;----------------------------------------------------------
IBUFE: EQU 0CF00H
ATRB: EQU 0CF00H
NAME: EQU 0CF01H
SIZE: EQU 0CF12H
DTADR: EQU 0CF14H
SUMDT: EQU 0FFE0H
TMCNT: EQU 0FFE2H
;
;
;INPUT BUFFER ADDRESS
;
IBADR1: EQU 0CF00H
IBADR2: EQU 8000H
;
; SUBROUTINE WORK
;
NTRACK: EQU 0FFE0H
NSECT: EQU 0FFE1H
BSIZE: EQU 0FFE2H
STTR: EQU 0FFE4H
STSE: EQU 0FFE5H
MTFG: EQU 0FFE6H
CLBF0: EQU 0FFE7H
CLBF1: EQU 0FFE8H
CLBF2: EQU 0FFE9H
CLBF3: EQU 0FFEAH
RETRY: EQU 0FFEBH
DRINO: EQU 0FFECH
;
;
;
;
;
; MFM MINIFLOPPY CONTROL
;
;
;
; CASE OF DISK INITIALIZE
; DRIVE NO=DRINO (0-3)
;
; CASE OF SEQUENTIAL READ
; DRIVE NO=DRINO (0-3)
; BYTE SIZE =IY+2,3
; ADDRESS =IX+0,1
; NEXT TRACK =IY+0
; NEXT SECTOR =IY+1
; START TRACK =IY+4
; START SECTOR =IY+5
;
;
; I/O PORT ADDRESS
;
CR: EQU 0D8H ;STATUS/COMMAND PORT
TR: EQU 0D9H ;TRACK REG PORT
SCR: EQU 0DAH ;SECTOR REG PORT
DR: EQU 0DBH ;DATA REG PORT
DM: EQU 0DCH ;MOTOR/DRIVE PORT
HS: EQU 0DDH ;HEAD SIDE SELECT PORT
PPIA: EQU 0E0H
PPIB: EQU 0E1H
PPIC: EQU 0E2H
PPICTL: EQU 0E3H
PIOA: EQU 0E8H
PIOCTLA:EQU 0E9H
PIOB: EQU 0EAH
PIOCTLB:EQU 0EBH
GRPHCTL:EQU 0F4H

661
software/asm/mz80kfdif.asm Normal file
View File

@@ -0,0 +1,661 @@
;
; MZ-80K FDC ROM
;
ORG F000H
F000 00 NOP
F001 F3 DI
F002 AF XOR A
F003 329C11 LD (#119C),A ;clock off
F006 3EC3 LD A,#C3 ;JP code for error trap
F008 320B10 LD (#100B),A
F00B 215AF0 LD HL,#F05A ;error can't boot
F00E 220C10 LD (#100C),HL ;error trap
F011 11F09F LD DE,#9FF0 ;transfer 9 bytes from
F014 2187F0 LD HL,#F087 ;ROM to RAM for use
;
;IBT1
;
F017 010900 IBT1: LD BC,#0009 ;by (IX+D) in reader
F01A EDB0 LDIR
F01C CD0900 CALL CRLF ;NL
F01F 117AF0 LD DE,MESS1
F022 CD1500 CALL MESSAGE ;msg "BOOT DRIVE ?"
F025 11009F LD DE,BUFF2
F028 CD0300 CALL USER ;get line
F02B 210C00 LD HL,#000C
F02E 19 ADD HL,DE ;skip around msg
F02F 7E LD A,(HL) ;pickup answer to prompt
F030 FE0D CP #0D ;CR ?
F032 2002 JR NZ,#F036 ;Z=CR assume drive 1
F034 3E31 LD A,#31 ;ASCII for 1
;
;IBT2
;
F036 47 IBT2: LD B,A ;save driveno
F037 E6F0 AND #F0 ;take ASCII and convert
F039 FE30 CP #30 ;to numeric having
F03B 20DF JR NZ,IBT1 ;checked >1 & <=4
F03D 78 LD A,B ;get driveno
F03E E60F AND #0F ;mask
F040 3D DEC A ;-1 00-03
F041 FE04 CP #04
F043 30D7 JR NC,IBT1 ;dud key, >=4, try again
F045 32F09F LD (#9FF0),A ;save drive no
F048 321110 LD (#1011),A ;save drive no
F04B DD21F09F LD IX,#9FF0 ;IX pointer to fdc parameters at 9FF0
;ready for disk read
F04F CD3BF1 CALL READER ;get boot records
F052 3A0098 LD A,(#9800) ;1st byte of input buffer of boot records
F055 FEC3 CP #C3 ;jump cmd?
F057 CA0098 JP Z,#9800 ;yes, execute to 9800
;
;IBT3
;
F05A 31F010 IBT3: LD SP,#10F0 ;no, reset stack
F05D CD0900 CALL CRLF ;NL
F060 116CF0 LD DE,MESS2 ;msg can't boot
F063 CD1500 CALL MESSAGE
F066 CDA7F0 CALL MOTOFF ;motor off
F069 C38200 JP MAINLP ;warm start, ret to monitor
;
;MESS2
;
F06C 45523A43 MESS2: DB "ER:CAN'T BOOT"
F070 414E2754
F074 20424F4F
F078 54
F079 0D DB 0DH
;
;MESS1
;
F07A 424F4F54 DB "BOOT DRIVE ?"
F07E 20445249
F082 5645203F
F086 0D DB 0DH
;
;DDATA
;fdc parameters
;
F087 00 DB 00H ;drive no-1
F088 00 DB 00H ;trk*2 remainder = head
F089 01 DB 01H ;sector no (range: 01 - 10)
F08A 00 DB 00H ;$80 = add 1 record to read to (F08B)
F08B 0700 DB 07H ;07H = 07*2 = 14 sectors to read, add 1 if (F08A = $80)
F08D 0098 DB 00H,98H ;9800H = load addr.
F08F 00 DB 00H ;no meaning
;
;MOTON
;
F090 C5 MOTON: PUSH BC ;starts motors
F091 01F808 LD BC,#08F8
F094 ED78 IN A,(C) ;start motor
F096 010000 LD BC,#0000
;
;WAIT1
;
F099 0B WAIT1: DEC BC ;wait for motor to
F09A 00 NOP ;get up to speed
F09B 00 NOP
F09C 78 LD A,B
F09D B1 OR C
F09E 20F9 JR NZ,WAIT1
F0A0 3E01 LD A,#01
F0A2 320210 LD (MOTFLG),A ;01=on 00=off
F0A5 C1 POP BC
F0A6 C9 RET
;
;MOTOFF
;
F0A7 C5 MOTOFF: PUSH BC ;stop motors
F0A8 CDAEF1 CALL LNGDEL ;timed wait
F0AB 01F800 LD BC,#00F8
F0AE ED78 IN A,(C)
F0B0 C1 POP BC
F0B1 C9 RET
;
;SKZERO
;
F0B2 CDBDF0 SKZERO: CALL DREADY ;seek track 0
F0B5 AF XOR A
F0B6 D3F9 OUT (#F9),A ;clear track reg
F0B8 320010 LD (#1000),A
F0BB D3FA OUT (#FA),A ;send seek zero code
;
;DREADY
;
F0BD C5 DREADY: PUSH BC
F0BE 010000 LD BC,#0000
;
;DRY1
;
F0C1 DBF9 DRY1: IN A,(#F9) ;get DRDY, CRDY, RQM
F0C3 E603 AND #03 ;leave DRDY, CRDY
;
;DRY2
;
F0C5 FE02 DRY2: CP #02 ;wait for DRDY & CRDY
F0C7 2002 JR NZ,WAIT2 ;no, =03
F0C9 C1 POP BC ;yes, =02
F0CA C9 RET
;
;WAIT2
;
F0CB 0B WAIT2: DEC BC
F0CC 78 LD A,B
F0CD B1 OR C
F0CE 20F1 JR NZ,DRY1
F0D0 C1 POP BC
F0D1 3E32 LD A,#32
F0D3 320810 LD (#1008),A ;error 40 (not found)
F0D6 C30B10 JP #100B ;error can't boot
;
;STATUS
;
F0D9 DBFA STATUS: IN A,(#FA) ;read status
F0DB E6F0 AND #F0
F0DD 07 RLCA
F0DE 30F9 JR NC,STATUS ;wait for CRDY
F0E0 E6F0 AND #F0 ;mask leave CRDY, S1, S2, S3
F0E2 0F RRCA ;move right until S§
F0E3 0F RRCA ;is in B0
F0E4 0F RRCA
F0E5 0F RRCA
F0E6 B7 OR A ;clear flags
F0E7 C8 RET Z ;Z=ok
F0E8 FE0C CP #0C ;0C=drive not ready etc.
F0EA 2004 JR NZ,STS1
F0EC 3E32 LD A,#32 ;error code 40 (not found)
F0EE 180A JR STS3
;
STS1
;
F0F0 FE04 STS1: CP #04 ;04=ID not found
F0F2 2004 JR NZ,STS2
F0F4 3E36 LD A,#36 ;error code 54 (unformat error)
F0F6 1802 JR STS3
;
;STS2
;
F0F8 3E29 STS2: LD A,#29
F0FA 320810 LD (#1008),A ;error code 41 disk hw error
F0FD 37 SCF
F0FE C9 RET
;
;PRMDRV
;
F0FF C5 PRMDRV: PUSH BC ;prime drive
F100 E5 PUSH HL
F101 CD90F0 CALL MOTON
F104 DD7E00 LD A,(IX+#00) ;get drive no-1
F107 E603 AND #03 ;form drive code
F109 F61C OR #1C ;set TND, MOTOR, SELECT BIT
F10B 320110 LD (#1001),A ;keep drive code
F10E E60F AND #0F ;mask out TND
F110 47 LD B,A
F111 0EF8 LD C,#F8
F113 ED60 IN H,(C) ;select drive
F115 3E32 LD A,#32
;
;PRM1
;
F117 CDAEF1 PRM1: CALL LNGDEL ;wait for head
F11A 3D DEC A :to load
F11B 20FA JR NZ,PRM1
F11D 010000 LD BC,#0000
;
;PRM2
;
F120 DBF9 PRM2: IN A,(#F9) ;get DRDY, CRDY, RQM
F122 E607 AND #07 ;mask out RUBBISH
F124 FE06 CP #06 ;DRDY & CRDY ?
F126 2006 JR NZ,PRM3 ;NZ=no, keep trying
F128 CDB2F0 CALL SKZERO
F12B E1 POP HL
F12C C1 POP BC
F12D C9 RET ;correct exit
;
;PRM3
;
F12E 0B PRM3: DEC BC
F12F 78 LD A,B
F130 B1 OR C
F131 20ED JR NZ,PRM2
F133 3E32 LD A,#32
F135 320810 LD (#1008),A ;error 40 (not found)
F138 C30B10 JP #100B ;abort; error can't boot
;
;READER
;
F13B 3E0A READER: LD A,#0A ;no. of tries
F13D 320710 LD (#1007),A
;
;RDR1
;
F140 CDFFF0 RDR1: CALL PRMDRV
F143 3A0110 LD A,(#1001) ;keep drive in use
F146 47 LD B,A
F147 0EF8 LD C,#F8
F149 D9 EXX ;save all regs
F14A 0EFB LD C,#FB ;port fb??
F14C DD5E03 LD E,(IX+#03) ;no meaning
F14F DD5604 LD D,(IX+#04) ;get half of numbers to read (7)
F152 CB13 RL E ;B7 to carry
F154 CB12 RL D ;double number of sectors (14), add carry
F156 1E03 LD E,#03 ;no meaning
F158 DD6E05 LD L,(IX+#05) ;get loading address lo
F15B DD6606 LD H,(IX+#06) ;hi into HL
F15E CDBDF0 CALL DREADY
F161 AF XOR A ;no meaning
F162 DD7E01 LD A,(IX+#01) ;get track to read
F165 1F RRA ;divide by 2, remainder to carry = head no.
F166 D3F9 OUT (#F9),A ;send track to FDC
F168 DD7E02 LD A,(IX+#02) ;sector number
F16B 3002 JR NC,RDR2
F16D F680 OR #80 ;odds/evens for side code
;
;RDR2
;
F16F D3F8 RDR2: OUT (#F8),A ;send sect+side
F171 CDA6F1 CALL SHTDEL ;short delay
F174 3E70 LD A,#70 ;seek & read code
F176 320010 LD (#1000),A ;keep it
F179 F3 DI
F17A D3FA OUT (#FA),A ;send seek & read code to FDC
;
;RDR3
;
F17C 0680 RDR3: LD B,#80 ;128 bytes/sector
;
;RDR4
;
F17E DBF9 RDR4: IN A,(#F9) ;get DRDY, CRDY, RQM
F180 A3 AND E ;mask with 03
F181 28FB JR Z,RDR4 ;wait for either CRDY/RQM
F183 0F RRCA ;RQM into carry
F184 300C JR NC,RDR5 ;NC=no RQM
F186 EDA2 INI ;get data. port FB to (HL), B=B-1
F188 C27EF1 JP NZ,RDR4 ;do whole sector
F18B 15 DEC D ;dec sector counter
F18C C27CF1 JP NZ,RDR3 ;NZ=more to do
F18F D9 EXX ;restore all regs
F190 ED78 IN A,(C) ;send TND high
;
;RDR5
;
F192 CDD9F0 RDR5: CALL STATUS
F195 D0 RET NC ;NC=good read
F196 3A0710 LD A,(#1007)
F199 3D DEC A ;A try gone
F19A 320710 LD (#1007),A ;counter 10times
F19D CA0B10 JP Z,#100B ;can't read at all abort
F1A0 CDB2F0 CALL SKZERO
F1A3 C340F1 JP RDR1
;
;SHTDEL
;
F1A6 F5 SHTDEL: PUSH AF
F1A7 3E0A LD A,#0A
;
;SDY1
;
F1A9 3D SDY1: DEC A
F1AA 20FD JR NZ,SDY1
F1AC F1 POP AF
F1AD C9 RET
;
;LNGDEL
;
F1AE F5 LNGDEL: PUSH AF ;long delay
F1AF 3E0A LD A,#0A
;
;LDY1
;
F1B1 CDA6F1 LDY1: CALL SHTDEL
F1B4 3D DEC A
F1B5 20FA JR NZ,LDY1
F1B7 F1 POP AF
F1B8 C9 RET
CRLF: EQU 00009H
MESSAGE: EQU 00015H
BUFF2: EQU 9F00H
USER: EQU 00003H
MAINLP: EQU 00082H
MOTFLG: EQU 1002H
END
;
;no meaning !!
;
F1B9 13 INC DE
F1BA 1B DEC DE
F1BB 72 LD (HL),D
F1BC DE42 SBC A,#42
F1BE FB EI
F1BF 2F CPL
F1C0 58 LD E,B
F1C1 43 LD B,E
F1C2 7C LD A,H
F1C3 52 LD D,D
F1C4 3023 JR NC,#F1E9 ; (35)
F1C6 71 LD (HL),C
F1C7 42 LD B,D
F1C8 1020 DJNZ #F1EA ; (32)
F1CA 74 LD (HL),H
F1CB 40 LD B,B
F1CC 43 LD B,E
F1CD 03 INC BC
F1CE 51 LD D,C
F1CF 00 NOP
F1D0 3C INC A
F1D1 42 LD B,D
F1D2 D8 RET C
F1D3 60 LD H,B
F1D4 FB EI
F1D5 09 ADD HL,BC
F1D6 FC402C CALL M,#2C40
F1D9 80 ADD A,B
F1DA 79 LD A,C
F1DB 2A4940 LD HL,(#4049)
F1DE 4D LD C,L
F1DF EE3E XOR #3E
F1E1 B2 OR D
F1E2 1EA2 LD E,#A2
F1E4 58 LD E,B
F1E5 02 LD (BC),A
F1E6 58 LD E,B
F1E7 12 LD (DE),A
F1E8 02 LD (BC),A
F1E9 43 LD B,E
F1EA 02 LD (BC),A
F1EB 220002 LD (#0200),HL
F1EE 2D DEC L
F1EF 4B LD C,E
F1F0 5A LD E,D
F1F1 0A LD A,(BC)
F1F2 40 LD B,B
F1F3 4A LD C,D
F1F4 13 INC DE
F1F5 42 LD B,D
F1F6 45 LD B,L
F1F7 0A LD A,(BC)
F1F8 5B LD E,E
F1F9 6E LD L,(HL)
F1FA 6A LD L,D
F1FB 4E LD C,(HL)
F1FC 4E LD C,(HL)
F1FD 4E LD C,(HL)
F1FE 5D LD E,L
F1FF 7E LD A,(HL)
F200 3011 JR NC,#F213 ; (17)
F202 DD300E JR NC,#F213 ; (14)
F205 067E LD B,#7E
F207 FE3A CP #3A
F209 CAC221 JP Z,#21C2
F20C 12 LD (DE),A
F20D 23 INC HL
F20E 13 INC DE
F20F 0D DEC C
F210 C20622 JP NZ,#2206
F213 C3C221 JP #21C2
F216 3AB830 LD A,(#30B8)
F219 FEB1 CP #B1
F21B CA4522 JP Z,#2245
F21E 2A5030 LD HL,(#3050)
F221 CD1E20 CALL #201E
F224 7E LD A,(HL)
F225 FE27 CP #27
F227 CA5722 JP Z,#2257
F22A 3E84 LD A,#84
F22C 327630 LD (#3076),A
F22F 3E02 LD A,#02
F231 327730 LD (#3077),A
F234 CDCA13 CALL #13CA
F237 D24A22 JP NC,#224A
F23A 2E00 LD L,#00
F23C 3EB2 LD A,#B2
F23E 32C830 LD (#30C8),A
F241 7D LD A,L
F242 326F30 LD (#306F),A
F245 3E01 LD A,#01
F247 C3C321 JP #21C3
F24A 3ABE30 LD A,(#30BE)
F24D FEC5 CP #C5
F24F C23C22 JP NZ,#223C
F252 3EB0 LD A,#B0
F254 C33E22 JP #223E
F257 23 INC HL
F258 7E LD A,(HL)
F259 E67F AND #7F
F25B 6F LD L,A
F25C C33C22 JP #223C
F25F 3AB830 LD A,(#30B8)
F262 FEB1 CP #B1
F264 CA9022 JP Z,#2290
F267 2A5030 LD HL,(#3050)
F26A CD1E20 CALL #201E
F26D 3E80 LD A,#80
F26F 327630 LD (#3076),A
F272 3E01 LD A,#01
F274 327730 LD (#3077),A
F277 CDCA13 CALL #13CA
F27A D29522 JP NC,#2295
F27D 210000 LD HL,#0000
F280 3E82 LD A,#82
F282 32C830 LD (#30C8),A
F285 226330 LD (#3063),HL
F288 116F30 LD DE,#306F
F28B 7C LD A,H
F28C 12 LD (DE),A
F28D 13 INC DE
F28E 7D LD A,L
F28F 12 LD (DE),A
F290 3E02 LD A,#02
F292 C3C321 JP #21C3
F295 3ABE30 LD A,(#30BE)
F298 FEC5 CP #C5
F29A C2A222 JP NZ,#22A2
F29D 3EB1 LD A,#B1
F29F C38222 JP #2282
F2A2 CDEA1A CALL #1AEA
F2A5 C38222 JP #2282
F2A8 2A5030 LD HL,(#3050)
F2AB CD1E20 CALL #201E
F2AE 116F30 LD DE,#306F
F2B1 0600 LD B,#00
F2B3 0E04 LD C,#04
F2B5 7E LD A,(HL)
F2B6 23 INC HL
F2B7 FE27 CP #27
F2B9 C2F822 JP NZ,#22F8
F2BC 7E LD A,(HL)
F2BD FE27 CP #27
F2BF C2DE22 JP NZ,#22DE
F2C2 3AB830 LD A,(#30B8)
F2C5 FEB1 CP #B1
F2C7 CAD522 JP Z,#22D5
F2CA AF XOR A
F2CB 21C830 LD HL,#30C8
F2CE B8 CP B
F2CF CAD922 JP Z,#22D9
F2D2 3EB3 LD A,#B3
F2D4 77 LD (HL),A
F2D5 78 LD A,B
F2D6 C3C321 JP #21C3
F2D9 3EB4 LD A,#B4
F2DB C3D422 JP #22D4
F2DE FE8D CP #8D
F2E0 CAF822 JP Z,#22F8
F2E3 FE0A CP #0A
F2E5 CAF822 JP Z,#22F8
F2E8 E67F AND #7F
F2EA 12 LD (DE),A
F2EB 23 INC HL
F2EC 13 INC DE
F2ED 04 INC B
F2EE 0D DEC C
F2EF C2BC22 JP NZ,#22BC
F2F2 117A30 LD DE,#307A
F2F5 C3BC22 JP #22BC
F2F8 3E53 LD A,#53
F2FA CD111C CALL #1C11
F2FD C3C222 JP #22C2
F300 CDE511 CALL #11E5
F303 CD0C20 CALL #200C
F306 FE3A CP #3A
F308 C26423 JP NZ,#2364
F30B 2A5030 LD HL,(#3050)
F30E CD1E20 CALL #201E
F311 3E80 LD A,#80
F313 327630 LD (#3076),A
F316 3E02 LD A,#02
F318 327730 LD (#3077),A
F31B CDCA13 CALL #13CA
F31E DA2E23 JP C,#232E
F321 3ACC30 LD A,(#30CC)
F324 FE01 CP #01
F326 C23123 JP NZ,#2331
F329 3ECC LD A,#CC
F32B CD111C CALL #1C11
F32E 210000 LD HL,#0000
F331 3AB830 LD A,(#30B8)
F334 FEB1 CP #B1
F336 CA6E23 JP Z,#236E
F339 FEB2 CP #B2
F33B CAC221 JP Z,#21C2
F33E 226330 LD (#3063),HL
F341 3EA2 LD A,#A2
F343 32C830 LD (#30C8),A
F346 CDB51D CALL #1DB5
F349 06DD LD B,#DD
F34B 30CD JR NC,#F31A ; (-51)
F34D E5 PUSH HL
F34E 1111DD LD DE,#DD11
F351 300E JR NC,#F361 ; (14)
F353 067E LD B,#7E
F355 FE3A CP #3A
F357 CAC221 JP Z,#21C2
F35A 12 LD (DE),A
F35B 23 INC HL
F35C 13 INC DE
F35D 0D DEC C
F35E C25423 JP NZ,#2354
F361 C3C221 JP #21C2
F364 3E4E LD A,#4E
F366 CD111C CALL #1C11
F369 3EB4 LD A,#B4
F36B C3BF21 JP #21BF
F36E EB EX DE,HL
F36F 2A4D31 LD HL,(#314D)
F372 2B DEC HL
F373 2B DEC HL
F374 2B DEC HL
F375 72 LD (HL),D
F376 23 INC HL
F377 73 LD (HL),E
F378 23 INC HL
F379 3680 LD (HL),#80
F37B C3C221 JP #21C2
F37E CC44A0 CALL Z,#A044
F381 41 LD B,C
F382 AC XOR H
F383 2842 JR Z,#F3C7 ; (66)
F385 C3A9F1 JP #F1A9
F388 0A LD A,(BC)
F389 CC44A0 CALL Z,#A044
F38C 41 LD B,C
F38D AC XOR H
F38E 2844 JR Z,#F3D4 ; (68)
F390 C5 PUSH BC
F391 A9 XOR C
F392 F1 POP AF
F393 1A LD A,(DE)
F394 CC44A0 CALL Z,#A044
F397 2842 JR Z,#F3DB ; (66)
F399 C3A9AC JP #ACA9
F39C 41 LD B,C
F39D F1 POP AF
F39E 02 LD (BC),A
F39F CC44A0 CALL Z,#A044
F3A2 2844 JR Z,#F3E8 ; (68)
F3A4 C5 PUSH BC
F3A5 A9 XOR C
F3A6 AC XOR H
F3A7 41 LD B,C
F3A8 F1 POP AF
F3A9 12 LD (DE),A
F3AA CC44A0 CALL Z,#A044
F3AD 41 LD B,C
F3AE AC XOR H
F3AF C9 RET
F3B0 F2ED57 JP P,#57ED
F3B3 CC44A0 CALL Z,#A044
F3B6 41 LD B,C
F3B7 AC XOR H
F3B8 D2F2ED JP NC,#EDF2
F3BB 5F LD E,A
F3BC CC44A0 CALL Z,#A044
F3BF C9 RET
F3C0 AC XOR H
F3C1 41 LD B,C
F3C2 F2ED47 JP P,#47ED
F3C5 CC44A0 CALL Z,#A044
F3C8 D2AC41 JP NC,#41AC
F3CB F2ED4F JP P,#4FED
F3CE CC44A0 CALL Z,#A044
F3D1 53 LD D,E
F3D2 50 LD D,B
F3D3 AC XOR H
F3D4 48 LD C,B
F3D5 CCF1F9 CALL Z,#F9F1
F3D8 CC44A0 CALL Z,#A044
F3DB 53 LD D,E
F3DC 50 LD D,B
F3DD AC XOR H
F3DE C9 RET
F3DF D8 RET C
F3E0 F2DDF9 JP P,#F9DD
F3E3 CC44A0 CALL Z,#A044
F3E6 53 LD D,E
F3E7 50 LD D,B
F3E8 AC XOR H
F3E9 C9 RET
F3EA 59 LD E,C
F3EB F2FDF9 JP P,#F9FD
F3EE 50 LD D,B
F3EF 55 LD D,L
F3F0 53 LD D,E
F3F1 48 LD C,B
F3F2 A0 AND B
F3F3 42 LD B,D
F3F4 C3F1C5 JP #C5F1
F3F7 50 LD D,B
F3F8 55 LD D,L
F3F9 53 LD D,E
F3FA 48 LD C,B
F3FB A0 AND B
F3FC 44 LD B,H
F3FD C5 PUSH BC
F3FE F1 POP AF
F3FF D5 PUSH DE

4853
software/asm/nascombasic.asm Normal file

File diff suppressed because it is too large Load Diff

155
software/asm/ramcheck.asm Normal file
View File

@@ -0,0 +1,155 @@
LETNL: EQU 0006h
PRNTS: EQU 000Ch
PRNT: EQU 0012h
MSG: EQU 0015h
MONIT: EQU 0086h
PRTHL: EQU 03BAh
PRTHX: EQU 03C3h
DPCT: EQU 0DDCh
MSTART: EQU 1200h
ORG 10F0h
DB 01h ; Code Type, 01 = Machine Code.
DB "RAM TEST V1.0", 0Dh, 00h, 00h ; Title/Name (17 bytes).
DW MSTART - START ; Size of program.
DW START ; Load address of program.
DW START ; Exec address of program.
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h ; Comment (104 bytes).
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
ORG 01200h
START: LD DE,TITLE
CALL MSG
CALL LETNL
LD B, 20 ; Number of loops
LOOP: LD HL,MSTART ; Start of checked memory,
LD D,0CEh ; End memory check CE00
LOOP1: LD A,000h
CP L
JR NZ,LOOP1b
CALL PRTHL ; Print HL as 4digit hex.
LD A,0C4h ; Move cursor left.
LD E,004h ; 4 times.
LOOP1a: CALL DPCT
DEC E
JR NZ,LOOP1a
LOOP1b: INC HL
LD A,H
CP D ; Have we reached end of memory.
JR Z,LOOP3 ; Yes, exit.
LD A,(HL) ; Read memory location under test, ie. 0.
CPL ; Subtract, ie. FF - A, ie FF - 0 = FF.
LD (HL),A ; Write it back, ie. FF.
SUB (HL) ; Subtract written memory value from A, ie. should be 0.
JR NZ,LOOP2 ; Not zero, we have an error.
LD A,(HL) ; Reread memory location, ie. FF
CPL ; Subtract FF - FF
LD (HL),A ; Write 0
SUB (HL) ; Subtract 0
JR Z,LOOP1 ; Loop if the same, ie. 0
LOOP2: LD A,16h
CALL PRNT ; Print A
CALL PRTHX ; Print HL as 4 digit hex.
CALL PRNTS ; Print space.
XOR A
LD (HL),A
LD A,(HL) ; Get into A the failing bits.
CALL PRTHX ; Print A as 2 digit hex.
CALL PRNTS ; Print space.
LD A,0FFh ; Repeat but first load FF into memory
LD (HL),A
LD A,(HL)
CALL PRTHX ; Print A as 2 digit hex.
NOP
JR LOOP4
LOOP3: LD DE,OKCHECK
CALL MSG ; Print check message in DE
LD A,B ; Print loop count.
CALL PRTHX
LD DE,OKMSG
CALL MSG ; Print ok message in DE
DEC B
JR NZ,LOOP
LD DE,DONEMSG
CALL MSG ; Print check message in DE
JP MONIT
OKCHECK: DB 11h
DB "CHECK: ", 0Dh
OKMSG: DB "OK.", 0Dh
DONEMSG: DB 11h
DB "RAM TEST COMPLETE.", 0Dh
LOOP4: LD B,09h
CALL PRNTS ; Print space.
XOR A ; Zero A
SCF ; Set Carry
LOOP5: PUSH AF ; Store A and Flags
LD (HL),A ; Store 0 to bad location.
LD A,(HL) ; Read back
CALL PRTHX ; Print A as 2 digit hex.
CALL PRNTS ; Print space
POP AF ; Get back A (ie. 0 + C)
RLA ; Rotate left A. Bit LSB becomes Carry (ie. 1 first instance), Carry becomes MSB
DJNZ LOOP5 ; Loop if not zero, ie. print out all bit locations written and read to memory to locate bad bit.
XOR A ; Zero A, clears flags.
LD A,80h
LD B,08h
LOOP6: PUSH AF ; Repeat above but AND memory location with original A (ie. 80)
LD C,A ; Basically walk through all the bits to find which one is stuck.
LD (HL),A
LD A,(HL)
AND C
NOP
JR Z,LOOP8 ; If zero then print out the bit number
NOP
NOP
LD A,C
CPL
LD (HL),A
LD A,(HL)
AND C
JR NZ,LOOP8 ; As above, if the compliment doesnt yield zero, print out the bit number.
LOOP7: POP AF
RRCA
NOP
DJNZ LOOP6
JP MONIT
LOOP8: CALL LETNL ; New line.
LD DE,BITMSG ; BIT message
CALL MSG ; Print message in DE
LD A,B
DEC A
CALL PRTHX ; Print A as 2 digit hex, ie. BIT number.
CALL LETNL ; New line
LD DE,BANKMSG ; BANK message
CALL MSG ; Print message in DE
LD A,H
CP 50h ; 'P'
JR NC,LOOP9 ; Work out bank number, 1, 2 or 3.
LD A,01h
JR LOOP11
LOOP9: CP 90h
JR NC,LOOP10
LD A,02h
JR LOOP11
LOOP10: LD A,03h
LOOP11: CALL PRTHX ; Print A as 2 digit hex, ie. BANK number.
JR LOOP7
BITMSG: DB " BIT: ", 0Dh
BANKMSG: DB " BANK: ", 0Dh
TITLE: DB "SHARPMZ RAM TEST (C) P. SMART 2018", 0Dh, 00h

File diff suppressed because it is too large Load Diff

View File

@@ -42,10 +42,14 @@ START: LD SP,STACK
CALL ?CLER ; Clear 256 bytes from NAME 10F1h to 11F0h
LD A,016H
CALL PRNT
IF MODE80C = 0
LD A,007H ; Black background, white characters. Bit 7 is clear as a write to bit 7 @ DFFFH selects 40Char mode.
IF KUMA = 1
LD A,0CFH
ELSE
LD A,017H ; Blue background, white characters in colour mode. Bit 7 is set as a write to bit 7 @ DFFFH selects 80Char mode.
IF MODE80C = 0
LD A,007H ; Black background, white characters. Bit 7 is clear as a write to bit 7 @ DFFFH selects 40Char mode.
ELSE
LD A,017H ; Blue background, white characters in colour mode. Bit 7 is set as a write to bit 7 @ DFFFH selects 80Char mode.
ENDIF
ENDIF
LD HL,ARAM
JR STRT1
@@ -130,13 +134,19 @@ LOAD: CALL ?RDI
JR C,ST1
JP (HL)
; LOADING
MSG?2: DB 04CH, 0B7H, 0A1H, 09CH
DB 0A6H, 0B0H, 097H, 020H
DB 00DH
; SIGN ON BANNER
MSG?3: DB "** MONITOR SA-1510 **", 0DH
; SIGN ON BANNER - Different for Kuma 80 BIOS
MSG?3: IF KUMA = 0
DB "** MONITOR SA-1510 **", 0DH
ELSE
DB "*K",0A5H,0B3H,0A1H," MZ-80A M",0B7H,0B0H,0A6H
DB 096H,0B7H,09DH,"*",00DH,"*",00DH
ENDIF
; For 80 Character mode we need some space, so shorten the Check Sum Error message.
;
@@ -148,7 +158,7 @@ MSGE1: IF MODE80C = 0
DB "CK SUM?", 0DH
ENDIF
; Hook = 7 bytes.
; Hook = 7 bytes using space taken from Check Sum message.
HOOK: IF MODE80C = 1
LD A,0FFH
LD (SPAGE),A
@@ -156,27 +166,56 @@ HOOK: IF MODE80C = 1
ENDIF
; CR PAGE MODE1
.CR: CALL .MANG
RRCA
JP NC,CURS2
LD L,000H
INC H
CP ROW - 1 ; End of line?
JR Z,.CP1
INC H
JP CURS1
.CR: IF KUMA = 1
LD HL,(DSPXY)
JP CURS2
ELSE
CALL .MANG
RRCA
JP NC,CURS2
LD L,000H
INC H
CP ROW - 1 ; End of line?
JR Z,.CP1
INC H
JP CURS1
ENDIF
.CR1: IF KUMA = 1
NEG
LD (SPAGE),A
ADD A,004H
LD (KEYPF),A
RET
DB 00EH
ENDIF
.CP1: LD (DSPXY),HL
; SCROLLER
.SCROL: LD BC,SCRNSZ - COLW ; Scroll COLW -1 lines
.SCROL: IF KUMA = 1
LD BC, 0780H
ELSE
LD BC,SCRNSZ - COLW ; Scroll COLW -1 lines
ENDIF
LD DE,SCRN ; Start of the screen.
LD HL,SCRN + COLW ; Start of screen + 1 line.
IF KUMA = 1
LD HL,0D050H
ELSE
LD HL,SCRN + COLW ; Start of screen + 1 line.
ENDIF
LDIR
EX DE,HL
LD B,COLW ; Clear last line at bottom of screen.
IF KUMA = 1
LD B, 050H
ELSE
LD B,COLW ; Clear last line at bottom of screen.
ENDIF
CALL ?CLER
LD BC,0001AH
IF KUMA = 1
JP ?RSTR
ELSE
LD BC,0001AH
ENDIF
LD DE,MANG
LD HL,MANG + 1
LDIR
@@ -587,22 +626,46 @@ TIMIN: PUSH AF
EI
RET
.DSP03: EX DE,HL
LD (HL),001H
INC HL
LD (HL),000H
JP CURSR
.MANG2: LD A,(DSPXY + 1)
ADD A,L
LD L,A
LD A,(HL)
INC HL
RL (HL)
OR (HL)
RR (HL)
RRCA
EX DE,HL
LD HL,(DSPXY)
.DSP03: IF KUMA = 1
LD A,(SPAGE)
OR A
LD A,027H
RET Z
ADD A,A
INC A
RET
L03A7: PUSH BC
CALL .DSP03
LD B,A
LD A,L
CP B
POP BC
RET
L03B0: CALL .DSP03
LD L,A
XOR A
DEC H
RET
ELSE
EX DE,HL
LD (HL),001H
INC HL
LD (HL),000H
JP CURSR
.MANG2: LD A,(DSPXY + 1)
ADD A,L
LD L,A
LD A,(HL)
INC HL
RL (HL)
OR (HL)
RR (HL)
RRCA
EX DE,HL
LD HL,(DSPXY)
ENDIF
RET
LD C,H
@@ -1141,7 +1204,11 @@ L0743: DEC H
?MODE: LD HL,KEYPF
LD (HL),08AH
LD (HL),007H
LD (HL),005H
IF KUMA = 1
LD (HL),004H
ELSE
LD (HL),005H
ENDIF
LD (HL),001H
RET
@@ -1270,7 +1337,11 @@ CHGPA: XOR A
JR CHGPK1
ENDIF
CHGPK: LD A,0FFH
CHGPK1: LD (SPAGE),A
CHGPK1: IF KUMA = 1
CALL .CR1
ELSE
LD (SPAGE),A
ENDIF
LD A,0C6H
CALL ?DPCT
CHGP1: JP GETL0
@@ -1581,7 +1652,12 @@ REV2: JP ?RSTR
.MANG: LD HL,MANG
LD A,(SPAGE)
OR A
JP NZ,.MANG2
IF KUMA = 1
JR NZ,.MANG1 ; (+018H)
NOP
ELSE
JP NZ,.MANG2
ENDIF
LD A,(MGPNT)
.MANG3: SUB 008H
INC HL
@@ -2407,14 +2483,24 @@ DLY12A: CALL DLY3
CALL ?PONT
LD (HL),B
LD HL,(DSPXY)
LD A,L
DSP01: CP COLW - 1 ; End of line.
IF KUMA = 1
CALL L03A7
ELSE
LD A,L
ENDIF
DSP01: IF KUMA = 0
CP COLW - 1 ; End of line.
ENDIF
JR NZ,DSP04
CALL .MANG
JR C,DSP04
LD A,(SPAGE)
OR A
JP NZ,.DSP03
IF KUMA
JP NZ,CURSR
ELSE
JP NZ,.DSP03
ENDIF
EX DE,HL
LD A,B
CP 007H
@@ -2535,8 +2621,12 @@ CURSU1: CALL MGP.D
JR CURS3
CURSR: LD HL,(DSPXY)
LD A,L
CP COLW - 1 ; End of line
IF KUMA = 1
CALL L03A7
ELSE
LD A,L
CP COLW - 1 ; End of line
ENDIF
JR NC,CURS2
INC L
JR CURS3
@@ -2555,8 +2645,12 @@ CURSL: LD HL,(DSPXY)
JR Z,CURS5A
DEC L
JR CURS3
CURS5A: LD L,COLW - 1 ; End of line
DEC H
CURS5A: IF KUMA = 1
CALL L03B0
ELSE
LD L,COLW - 1 ; End of line
DEC H
ENDIF
JP P,CURSU1
LD H,000H
LD (DSPXY),HL
@@ -2643,13 +2737,24 @@ INST: CALL .MANG
RRCA
LD L,COLW - 1 ; End of line
LD A,L
JR NC,INST1A
INC H
INST1A: CALL ?PNT1
PUSH HL
LD HL,(DSPXY)
JR NC,INST2
LD A,(COLW*2)-1 ; 04FH
IF KUMA = 1
JR NC,INST1B
LD A,028H
ADD A,L
LD L,A
INST1B: CALL ?PNT1
PUSH HL
LD HL,(DSPXY)
NOP
ELSE
JR NC,INST1A
INC H
INST1A: CALL ?PNT1
PUSH HL
LD HL,(DSPXY)
JR NC,INST2
LD A,(COLW*2)-1 ; 04FH
ENDIF
INST2: SUB L
LD B,A
POP DE
@@ -2720,16 +2825,30 @@ ROLU1: CALL MGP.I
PUSH HL
POP BC
LD DE,COLW
LD HL,SCRN - COLW
LD A,(SPAGE)
OR A
JR NZ,?PNT2
LD HL,(PAGETP)
SBC HL,DE
?PNT2: ADD HL,DE
DEC B
JP P,?PNT2
LD B,000H
IF KUMA = 1
LD HL,(PAGETP)
INC B
LD A,(SPAGE)
OR A
JR Z,L0FCE ; (+008H)
LD HL,0D000H
LD E,050H
JR L0FCE ; (+001H)
L0FCD: ADD HL,DE
L0FCE: DJNZ L0FCD ; (-003H)
NOP
ELSE
LD HL,SCRN - COLW
LD A,(SPAGE)
OR A
JR NZ,?PNT2
LD HL,(PAGETP)
SBC HL,DE
?PNT2: ADD HL,DE
DEC B
JP P,?PNT2
LD B,000H
ENDIF
ADD HL,BC
RES 3,H
POP DE

1658
software/asm/sfd700.asm Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2254
software/asm/testtz.asm Normal file

File diff suppressed because it is too large Load Diff

2522
software/asm/tzfs.asm Normal file

File diff suppressed because it is too large Load Diff

553
software/asm/tzfs_bank2.asm Normal file
View File

@@ -0,0 +1,553 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: tzfs_bank2.asm
;- Created: July 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- Bank 2 - F000:FFFF - Help and messages
;-
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- Credits:
;- Copyright: (c) 2018-2020 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;- Dec 2020 - Updates to accommodate v1.3 of the tranZPUter SW-700 board where soft
;- CPU's now become possible.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;============================================================
;
; TZFS BANK 2 - Help and message functions.
;
;============================================================
ORG BANKRAMADDR
;-------------------------------------------------------------------------------
; START OF PRINT ROUTINE METHODS
;-------------------------------------------------------------------------------
; Method to print out a true ASCII character, not the Sharp values. This is done using the mapping table ATBL for the
; range 0..127, 128.. call the original Sharp routine.
; Input: A = Ascii character.
PRINTASCII: PUSH HL
PUSH BC
CP 080H ; Anything above 080H isnt ascii so call original routine.
JR NC,PRINTASCII1
CP 00DH ; Carriage Return? Dont map just execute via original Sharp call.
JR Z,PRINTASCII1
LD HL,ATBL
LD C,A
LD B,0
ADD HL,BC
LD A,(HL)
CALL ?DSP
PRINTASCII0:POP BC
POP HL
RET
PRINTASCII1:CALL PRNT
JR PRINTASCII0
; Method to print out a string residing in this bank.
;
; As string messages take up space and banks are limited, it makes sense to locate all strings in one
; bank and print them out from here, hence this method.
;
; Also, as strings often require embedded values to be printed (aka printf), a basic mechanism for printing out stack
; parameters is provided. A PUSH before calling this method followed by an embedded marker (ie. 0xFF) will see the stack
; value printed in hex at the point in the string where the marker appears.
;
; Input: DE = Address, in this bank or any other location EXCEPT another bank.
; BC = Value to print with marker 0xFB if needed.
; Upto 4 stack values accessed by markers 0xFF, 0xFE, 0xFD, 0xFC
PRINTMSG: LD A,(DE)
CP 000H ; End of string?
RET Z
CP 0FFH ; Marker to print out first stack parameter.
JR Z,PRINTMSG3
CP 0FEH ; Marker to print out second stack parameter.
JR Z,PRINTMSG6
CP 0FDH ; Marker to print out third stack parameter.
JR Z,PRINTMSG7
CP 0FCH ; Marker to print out fourth stack parameter.
JR Z,PRINTMSG8
CP 0FBH ; Marker to print out BC.
JR Z,PRINTMSG9
CP 0FAH ; Marker to print out a filename with filename address stored in BC.
JR Z,PRINTMSG10
CALL PRINTASCII
PRINTMSG2: INC DE
JR PRINTMSG
PRINTMSG3: LD HL,6+0 ; Get first stack parameter, there are 2 pushes on the stack plus return address before the parameters.
PRINTMSG4: ADD HL,SP
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
PRINTMSG5: CALL PRTHL
JR PRINTMSG2
PRINTMSG6: LD HL,6+2
JR PRINTMSG4
PRINTMSG7: LD HL,6+4
JR PRINTMSG4
PRINTMSG8: LD HL,6+6
JR PRINTMSG4
PRINTMSG9: PUSH BC ; Print out contents of BC as 4 digit hex.
POP HL
JR PRINTMSG5
PRINTMSG10: PUSH DE ; Print out a filename with pointer stored in BC.
PUSH BC
POP DE
CALL PRTFN
POP DE
JR PRINTMSG2
; Method to print out the filename within an MZF header or SD Card header.
; The name may not be terminated as the full 17 chars are used, so this needs
; to be checked. Also, the filename uses Sharp Ascii so call the original Sharp
; print routine.
;
; Input: DE = Address of filename.
;
PRTFN: PUSH BC
LD B,FNSIZE ; Maximum size of filename.
PRTMSG: LD A,(DE)
INC DE
CP 000H ; If there is a valid terminator, exit.
JR Z,PRTMSGE
CP 00DH
JR Z,PRTMSGE
CALL PRNT
DJNZ PRTMSG ; Else print until 17 chars have been processed.
CALL NL
PRTMSGE: POP BC
RET
; A modified print string routine with full screen pause to print out the help screen text. The routine prints out true ascii
; as opposed to Sharp modified ascii.
; A string is NULL terminated.
PRTSTR: PUSH AF
PUSH BC
PUSH DE
LD A,0
LD (TMPLINECNT),A
PRTSTR1: LD A,(DE)
CP 000H ; NULL terminates the string.
JR Z,PRTSTRE
CP 00DH ; As does CR.
JR Z,PRTSTR3
PRTSTR2: CALL PRINTASCII
INC DE
JR PRTSTR1
PRTSTR3: PUSH AF
LD A,(TMPLINECNT)
CP 23 ; Check to see if a page of output has been displayed, if it has, pause.
JR Z,PRTSTR5
INC A
PRTSTR4: LD (TMPLINECNT),A
POP AF
JR PRTSTR2
PRTSTR5: CALL GETKY
CP ' '
JR NZ,PRTSTR5
XOR A
JR PRTSTR4
PRTSTRE: POP DE
POP BC
POP AF
RET
; Method to convert a string with Sharp ASCII codes into standard ASCII codes via map lookup.
; Inputs: DE = pointer to string for conversion.
; B = Maximum number of characters to convert if string not terminated.
;
CNVSTR_SA: PUSH HL
PUSH DE
PUSH BC
CNVSTRSA1: LD A,(DE) ; Get character for conversion.
OR A ; Exit at End of String (NULL, CR)
JR Z,CNVSTRSAEX
CP 00DH
JR Z,CNVSTRSAEX
CP 020H ; No point mapping control characters.
JR C,CNVSTRSA2
;
LD HL,SHARPTOASC ; Start of mapping table.
PUSH BC
LD C,A
LD B,0
ADD HL,BC ; Add in character offset.
POP BC
LD A,(HL)
LD (DE),A ; Map character.
CNVSTRSA2: INC DE
DJNZ CNVSTRSA1
CNVSTRSAEX: POP BC ; Restore all registers used except AF.
POP DE
POP HL
RET
; Method to convert a string with standard ASCII into Sharp ASCII codes via scan lookup in the mapping table.
; Inputs: DE = pointer to string for conversion.
; B = Maximum number of characters to convert if string not terminated.
CNVSTR_AS: PUSH HL
PUSH DE
PUSH BC
CNVSTRAS1: LD A,(DE) ; Get character for conversion.
OR A ; Exit at End of String (NULL, CR)
JR Z,CNVSTRSAEX
CP 00DH
JR Z,CNVSTRSAEX
CP 020H ; No point mapping control characters.
JR C,CNVSTRAS5
LD HL,SHARPTOASC + 020H
PUSH BC
LD B, 0100H - 020H
CNVSTRAS2: CP (HL) ; Go through table looking for a match.
JR Z,CNVSTRAS3
INC HL
DJNZ CNVSTRAS2
JR CNVSTRAS4 ; No match then dont convert.
CNVSTRAS3: LD BC,SHARPTOASC ; On match or expiration of BC subtract table starting point to arrive at index.
OR A
SBC HL,BC
LD A,L ; Index is used as the converted character.
CNVSTRAS4: LD (DE),A
POP BC
CNVSTRAS5: INC DE
DJNZ CNVSTRAS1
JR CNVSTRSAEX
; TRUE ASCII TO DISPLAY CODE TABLE
;
ATBL: DB 0CCH ; NUL '\0' (null character)
DB 0E0H ; SOH (start of heading)
DB 0F2H ; STX (start of text)
DB 0F3H ; ETX (end of text)
DB 0CEH ; EOT (end of transmission)
DB 0CFH ; ENQ (enquiry)
DB 0F6H ; ACK (acknowledge)
DB 0F7H ; BEL '\a' (bell)
DB 0F8H ; BS '\b' (backspace)
DB 0F9H ; HT '\t' (horizontal tab)
DB 0FAH ; LF '\n' (new line)
DB 0FBH ; VT '\v' (vertical tab)
DB 0FCH ; FF '\f' (form feed)
DB 0FDH ; CR '\r' (carriage ret)
DB 0FEH ; SO (shift out)
DB 0FFH ; SI (shift in)
DB 0E1H ; DLE (data link escape)
DB 0C1H ; DC1 (device control 1)
DB 0C2H ; DC2 (device control 2)
DB 0C3H ; DC3 (device control 3)
DB 0C4H ; DC4 (device control 4)
DB 0C5H ; NAK (negative ack.)
DB 0C6H ; SYN (synchronous idle)
DB 0E2H ; ETB (end of trans. blk)
DB 0E3H ; CAN (cancel)
DB 0E4H ; EM (end of medium)
DB 0E5H ; SUB (substitute)
DB 0E6H ; ESC (escape)
DB 0EBH ; FS (file separator)
DB 0EEH ; GS (group separator)
DB 0EFH ; RS (record separator)
DB 0F4H ; US (unit separator)
DB 000H ; SPACE
DB 061H ; !
DB 062H ; "
DB 063H ; #
DB 064H ; $
DB 065H ; %
DB 066H ; &
DB 067H ; '
DB 068H ; (
DB 069H ; )
DB 06BH ; *
DB 06AH ; +
DB 02FH ; ,
DB 02AH ; -
DB 02EH ; .
DB 02DH ; /
DB 020H ; 0
DB 021H ; 1
DB 022H ; 2
DB 023H ; 3
DB 024H ; 4
DB 025H ; 5
DB 026H ; 6
DB 027H ; 7
DB 028H ; 8
DB 029H ; 9
DB 04FH ; :
DB 02CH ; ;
DB 051H ; <
DB 02BH ; =
DB 057H ; >
DB 049H ; ?
DB 055H ; @
DB 001H ; A
DB 002H ; B
DB 003H ; C
DB 004H ; D
DB 005H ; E
DB 006H ; F
DB 007H ; G
DB 008H ; H
DB 009H ; I
DB 00AH ; J
DB 00BH ; K
DB 00CH ; L
DB 00DH ; M
DB 00EH ; N
DB 00FH ; O
DB 010H ; P
DB 011H ; Q
DB 012H ; R
DB 013H ; S
DB 014H ; T
DB 015H ; U
DB 016H ; V
DB 017H ; W
DB 018H ; X
DB 019H ; Y
DB 01AH ; Z
DB 052H ; [
DB 059H ; \ '\\'
DB 054H ; ]
DB 0BEH ; ^
DB 03CH ; _
DB 0C7H ; `
DB 081H ; a
DB 082H ; b
DB 083H ; c
DB 084H ; d
DB 085H ; e
DB 086H ; f
DB 087H ; g
DB 088H ; h
DB 089H ; i
DB 08AH ; j
DB 08BH ; k
DB 08CH ; l
DB 08DH ; m
DB 08EH ; n
DB 08FH ; o
DB 090H ; p
DB 091H ; q
DB 092H ; r
DB 093H ; s
DB 094H ; t
DB 095H ; u
DB 096H ; v
DB 097H ; w
DB 098H ; x
DB 099H ; y
DB 09AH ; z
DB 0BCH ; {
DB 080H ; |
DB 040H ; }
DB 0A5H ; ~
DB 0C0H ; DEL
ATBLE: EQU $
; Mapping table to convert between Sharp ASCII and standard ASCII.
; Sharp -> ASCII : Index with Sharp value into table to obtain conversion.
; ASCII -> Sharp : Scan into table looking for value, on match the idx is the conversion. NB 0x20 = 0x20.
SHARPTOASC: DB 000H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 000H, 020H, 020H ; 0x0F
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0x1F
DB 020H, 021H, 022H, 023H, 024H, 025H, 026H, 027H, 028H, 029H, 02AH, 02BH, 02CH, 02DH, 02EH, 02FH ; 0x2F
DB 030H, 031H, 032H, 033H, 034H, 035H, 036H, 037H, 038H, 039H, 03AH, 03BH, 03CH, 03DH, 03EH, 03FH ; 0x3F
DB 040H, 041H, 042H, 043H, 044H, 045H, 046H, 047H, 048H, 049H, 04AH, 04BH, 04CH, 04DH, 04EH, 04FH ; 0x4F
DB 050H, 051H, 052H, 053H, 054H, 055H, 056H, 057H, 058H, 059H, 05AH, 05BH, 05CH, 05DH, 05EH, 05FH ; 0x5F
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0x6F
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0x7F
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0x8F
DB 020H, 020H, 065H, 020H, 020H, 020H, 074H, 067H, 068H, 020H, 062H, 078H, 064H, 072H, 070H, 063H ; 0x9F
DB 071H, 061H, 07AH, 077H, 073H, 075H, 069H, 020H, 04FH, 06BH, 066H, 076H, 020H, 075H, 042H, 06AH ; 0xAF
DB 06EH, 020H, 055H, 06DH, 020H, 020H, 020H, 06FH, 06CH, 041H, 06FH, 061H, 020H, 079H, 020H, 020H ; 0xBF
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0xCF
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0xDF
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0xEF
DB 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H, 020H ; 0xFF
;-------------------------------------------------------------------------------
; END OF PRINT ROUTINE METHODS
;-------------------------------------------------------------------------------
; The FDC controller uses it's busy/wait signal as a ROM address line input, this
; causes a jump in the code dependent on the signal status. It gets around the 2MHz Z80 not being quick
; enough to process the signal by polling.
ALIGN_NOPS FDCJMP1
ORG FDCJMP1
FDCJMPL2: JP (IX)
;-------------------------------------------------------------------------------
;
; Message table
;
;-------------------------------------------------------------------------------
; 0 + <- 39
; -----------------------------------------
MSGSON: DB "+ TZFS v1.6 ", NULL ; Version 1.0-> first split from RFS v2.0
MSGSONEND: DB " **", CR, NULL ; Signon banner termination.
MSGSONT80: DB "(T80)", NULL ; T80 CPU detected.
MSGNOTFND: DB "Not Found", CR, NULL
MSGBADCMD: DB "???", CR, NULL
MSGSDRERR: DB "SD Read error, Sec:",0FBH, NULL
MSGSVFAIL: DB "Save failed.", CR, NULL
MSGERAFAIL: DB "Erase failed.", CR, NULL
MSGCDFAIL: DB "Directory invalid.", CR, NULL
MSGERASEDIR:DB "Deleted dir entry:",0FBH, NULL
MSGCMTDATA: DB "Load:",0FEH,",Exec:",0FFH, ",Size:", 0FBH, CR, NULL
MSGNOTBIN: DB "Not binary", CR, NULL
MSGLOAD: DB CR, "Loading ",'"',0FAH,'"', CR, NULL
MSGSAVE: DB CR, "Filename: ", NULL
MSGE1: DB CR, "Check sum error!", CR, NULL ; Check sum error.
MSGCMTWRITE:DB CR, "Writing ", '"',0FAH,'"', CR, NULL
MSGOK: DB CR, "OK!", CR, NULL
MSGSAVEOK: DB "Tape image saved.", CR, NULL
MSGBOOTDRV: DB CR, "Floppy boot drive ?", NULL
MSGLOADERR: DB CR, "Disk loading error", CR, NULL
MSGIPLLOAD: DB CR, "Disk loading ", NULL
MSGDSKNOTMST:DB CR, "This is not a boot disk", CR, NULL
MSGINITM: DB "Init memory", CR, NULL
MSGREAD4HEX:DB "Bad hex number", CR, NULL
MSGT2SDERR: DB "Copy from Tape to SD Failed", CR, NULL
MSGSD2TERR: DB "Copy from SD to Tape Failed", CR, NULL
MSGT2SDOK: DB "Success, Tape to SD done.", CR, NULL
MSGSD2TOK: DB "Success, SD to Tape done.", CR, NULL
MSGUNKNHW: DB "Unknown hardware, cannot change!", CR, NULL
MSGFAILBIOS:DB "Failed to load alternate BIOS!", CR, NULL
MSGFAILEXIT:DB "TZFS exit failed, I/O proc error!", CR, NULL
MSGFREQERR: DB "Error, failed to change frequency!", CR, NULL
MSGBADNUM: DB "Error, bad number supplied!", CR, NULL
MSGNOFPGA: DB "Error, no FPGA video module!", CR, NULL
MSGT80ERR: DB "Error, failed to switch to T80 CPU!", CR, NULL
MSGZ80ERR: DB "Error, failed to switch to Z80 CPU!", CR, NULL
MSGZPUERR: DB "Error, failed to switch to ZPU CPU!", CR, NULL
MSGNOSOFTCPU:DB "No soft cpu hardware!", CR, NULL
MSGNOT80CPU:DB "T80 not available!", CR, NULL
MSGNOEMU: DB "No Sharp MZ Series Emu hardware!", CR, NULL
;
OKCHECK: DB ", CHECK: ", CR, NULL
OKMSG: DB " OK.", CR, NULL
DONEMSG: DB 11h
DB "RAM TEST COMPLETE.", CR, NULL
BITMSG: DB " BIT: ", CR, NULL
BANKMSG: DB " BANK: ", CR, NULL
MSG_TIMERTST:DB "8253 TIMER TEST", CR, NULL
MSG_TIMERVAL:DB "READ VALUE 1: ", CR, NULL
MSG_TIMERVAL2:DB "READ VALUE 2: ", CR, NULL
MSG_TIMERVAL3:DB "READ DONE.", CR, NULL
; The FDC controller uses it's busy/wait signal as a ROM address line input, this
; causes a jump in the code dependent on the signal status. It gets around the 2MHz Z80 not being quick
; enough to process the signal by polling.
ALIGN_NOPS FDCJMP2
ORG FDCJMP2
FDCJMPH2: JP (IY)
; Continuation of messages after the Floppy Disk controller fixed location.
MSGNOZPUCPU:DB "ZPU Evo not available!", CR, NULL
MSGNOCMTDIR:DB "CMT has no directory.", CR, NULL
MSGNOVERIFY:DB "No Verify for SD drive.", CR, NULL
SVCRESPERR: DB "I/O Response Error, time out!", CR, NULL
SVCIOERR: DB "I/O Error, time out!", CR, NULL
;TESTMSG: DB "HL is:",0FBH, 00DH, 000H
;TESTMSG2: DB "DE is:",0FBH, 00DH, 000H
;TESTMSG3: DB "BC is:",0FBH, 00DH, 000H
;TESTMSG4: DB "4 is:",0FBH, 00DH, 000H
;-------------------------------------------------------------------------------
; START OF HELP SCREEN FUNCTIONALITY
;-------------------------------------------------------------------------------
; Simple help screen to display commands.
HELP: ;CALL NL
LD DE, HELPSCR
CALL PRTSTR
RET
; Help text. Use of lower case, due to Sharp's non standard character set, is not easy, you have to manually code each byte
; hence using upper case.
HELPSCR: ; "--------- 40 column width -------------"
DB "4 40 col mode.", 00DH
DB "8 80 col mode.", 00DH
;DB "40A select MZ-80A 40col Mode.", 00DH
;DB "80A select MZ-80A 80col Mode.", 00DH
;DB "80B select MZ-80B Mode.", 00DH
;DB "700 select MZ-700 40col Mode.", 00DH
;DB "7008 select MZ-700 80col Mode.", 00DH
DB "B toggle keyboard bell.", 00DH
DB "BASIC load BASIC SA-5510.", 00DH
DB "C[b] clear memory $1200-$D000.", 00DH
DB "CD[d] switch to SD directory [d].", 00DH
DB "CPM load CPM.", 00DH
DB "DXXXX[YYYY] dump mem XXXX to YYYY.", 00DH
DB "DIR[wc] SD dir listing, wc=wildcard.", 00DH
DB "ECfn erase file, fn=No or Filename", 00DH
DB "EX exit TZFS, reset as original.", 00DH
DB "Fx boot fd drive x.", 00DH
DB "FREQn set CPU to nKHz, 0 default.", 00DH
DB "H this help screen.", 00DH
DB "JXXXX jump to location XXXX.", 00DH
DB "LTfn[,M] load tape, fn=Filename", 00DH
DB " M = HW Mode, K=80K,C=80C,1=1200", 00DH
DB " A=80A,7=700,8=800,B=80B,2=2000", 00DH
DB "LCfn[,M] load from SD, fn=No or FileN", 00DH
DB " add NX for no exec, ie.LCNX.", 00DH
DB "MXXXX edit memory starting at XXXX.", 00DH
DB "MZmc activate hardware emulation.", 00DH
DB " mc =80K,80C,1200,80A,700,800,80B,2000", 00DH
DB "P test printer.", 00DH
DB "R test dram memory.", 00DH
DB "SDDd change to SD directory {d}.", 00DH
DB "SD2Tfn[,M] copy SD to tape.", 00DH
DB "STXXXXYYYYZZZZ[,M] save mem to tape.", 00DH
DB "SCXXXXYYYYZZZZ save mem to card.", 00DH
DB " XXXX=start, YYYY=end, ZZZZ=exec", 00DH
DB "T test timer.", 00DH
DB "T2SD[B][,M] copy tape to SD, B=Bulk", 00DH
DB "T80 switch to soft T80 CPU.", 00DH
DB "V verify tape save.", 00DH
DB "VBORDERn set vga border colour.", 00DH
DB "VMODEn set video mode.", 00DH
DB "VGAn set VGA mode.", 00DH
DB "Z80 switch to hard Z80 CPU.", 00DH
DB "ZPU switch to ZPU Evo CPU / zOS.", 00DH
; "--------- 40 column width -------------"
DB 000H
;-------------------------------------------------------------------------------
; END OF HELP SCREEN FUNCTIONALITY
;-------------------------------------------------------------------------------
;
; Ensure we fill the entire 4K by padding with FF's.
;
ALIGN_NOPS 10000H

1169
software/asm/tzfs_bank3.asm Normal file

File diff suppressed because it is too large Load Diff

344
software/asm/tzfs_bank4.asm Normal file
View File

@@ -0,0 +1,344 @@
;--------------------------------------------------------------------------------------------------------
;-
;- Name: tzfs_bank4.asm
;- Created: July 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- Bank 4 - F000:FFFF -
;-
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- Credits:
;- Copyright: (c) 2018-2020 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;- Dec 2020 - Updates to accommodate v1.3 of the tranZPUter SW-700 board where soft
;- CPU's now become possible.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;============================================================
;
; TZFS BANK 4 - TZFS commands
;
;============================================================
ORG BANKRAMADDR
;-------------------------------------------------------------------------------
; START OF ADDITIONAL TZFS COMMANDS
;-------------------------------------------------------------------------------
; Method to set the video mode.
; Param: 0 - Enable FPGA and set to MZ-80K mode.
; 1 - Enable FPGA and set to MZ-80C mode.
; 2 - Enable FPGA and set to MZ-1200 mode.
; 3 - Enable FPGA and set to MZ-80A mode (base mode on MZ-80A hardware).
; 4 - Enable FPGA and set to MZ-700 mode (base mode on MZ-700 hardware).
; 5 - Enable FPGA and set to MZ-1500 mode.
; 6 - Enable FPGA and set to MZ-800 mode.
; 7 - Enable FPGA and set to MZ-80B mode.
; 8 - Enable FPGA and set to MZ-2000 mode.
; 9 - Enable FPGA and set to MZ-2200 mode.
; 10 - Enable FPGA and set to MZ-2500 mode.
; O - Turn off FPGA Video, turn on mainboard video.
SETVMODE: IN A,(CPLDINFO) ; Get configuration of hardware.
BIT 3,A
JP Z,NOFPGAERR ; No hardware so cannot change mode.
PUSH DE ; Preserve DE in case no number given.
POP BC
CALL ConvertStringToNumber ; Convert the input into 0 (disable) or frequency in KHz.
JR NZ,SETVMODEOFF
LD A,H
CP 0
JP NZ,BADNUMERR ; Check that the given mode is in range 0 - 7.
LD A,L
CP 10
JP NC,BADNUMERR
;
SETVMODE0: IN A,(CPLDCFG)
OR MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to enable the FPGA video mode.
OUT (CPLDCFG),A
;
IN A,(VMCTRL) ; Get current setting.
AND 0F0H ; Clear old mode setting.
OR L ; Add in new setting.
OUT (VMCTRL),A
RLC L ; Shift mode to position for SCRNMODE storage.
RLC L
RLC L
RLC L
LD A,(SCRNMODE) ; Repeat for the screen mode variable, used when resetting or changing display settings.
AND 007H ; Clear video mode setting.
OR L ; Add in new setting.
SET 2, A ; Set flag to indicate video mode override - ie, dont use base machine mode.
SETVMODECLR:SET 1, A ; Ensure flag set so on restart the FPGA video mode is selected.
LD (SCRNMODE),A
LD A, 016H ; Clear the screen so we start from a known position.
CALL PRNT
LD A,071H ; Blue background and white characters.
LD HL,ARAM
CALL CLR8
RET
SETVMODEOFF:LD A,(DE)
CP 'O'
JR Z,SETVMODE1
CP 'o'
JP NZ,BADNUMERR
SETVMODE1: LD A,(SCRNMODE) ; Disable flag to enable FPGA on restart.
RES 1,A
LD (SCRNMODE),A
IN A,(CPLDCFG)
AND ~MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to disable the FPGA video mode.
OUT (CPLDCFG),A
RET
; Method to set the VGA output mode of the external display.
SETVGAMODE: IN A,(CPLDINFO) ; Get configuration of hardware.
BIT 3,A
JP Z,NOFPGAERR ; No hardware so cannot change mode.
CALL ConvertStringToNumber ; Convert the input into 0-3, 0 = off, 1 = 640x480, 2=1024x768, 3=800x600.
JP NZ,BADNUMERR
LD A,H
CP 0
JP NZ,BADNUMERR ; Check that the given mode is in range 0 - 15.
LD A,L
CP 15
JP NC,BADNUMERR
;
;RRC L
;RRC L ; Value to top 2 bits ready to be applied to VGA mode register.
;
SETVGAMODE1:IN A,(CPLDCFG)
OR MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to enable the FPGA video mode.
OUT (CPLDCFG),A
;
LD A, L ; Add in new setting.
OUT (VMVGAMODE),A
LD (SCRNMODE2), A
JP SETVMODECLR
; Method to set the VGA border colour on the external display.
SETVBORDER: IN A,(CPLDINFO) ; Get configuration of hardware.
BIT 3,A
JP Z,NOFPGAERR ; No hardware so cannot change mode.
CALL ConvertStringToNumber ; Convert the input into 0 - 7, bit 2 = Red, 1 = Green, 0 = Blue.
JP NZ,BADNUMERR
LD A,H
CP 0
JP NZ,BADNUMERR ; Check that the given mode is in range 0 - 7.
LD A,L
CP 7
JP NC,BADNUMERR
;
IN A,(CPLDCFG)
OR MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to enable the FPGA video mode.
OUT (CPLDCFG),A
;
LD A,L
OUT (VMVGATTR),A
RET
; Method to enable/disable the alternate CPU frequency and change it's values.
;
SETFREQ: CALL ConvertStringToNumber ; Convert the input into 0 (disable) or frequency in KHz.
JP NZ,BADNUMERR
LD (TZSVC_CPU_FREQ),HL ; Set the required frequency in the service structure.
LD A,H
CP L
JR NZ,SETFREQ1
LD A, TZSVC_CMD_CPU_BASEFREQ ; Switch to the base frequency.
JR SETFREQ2
SETFREQ1: LD A, TZSVC_CMD_CPU_ALTFREQ ; Switch to the alternate frequency.
SETFREQ2: CALL SVC_CMD
OR A
JP NZ,SETFREQERR
LD A,H
CP L
RET Z ; If we are disabling the alternate cpu frequency (ie. = 0) exit.
LD A, TZSVC_CMD_CPU_CHGFREQ ; Switch to the base frequency.
CALL SVC_CMD
OR A
JP NZ,SETFREQERR
RET
; Method to configure the hardware to use the T80 CPU instantiated in the FPGA.
;
SETT80: IN A,(CPUINFO)
LD C,A
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JP NZ,SOFTCPUERR
LD A,C
AND CPUMODE_IS_T80
JP Z,NOT80ERR
;LD L,VMMODE_VGA_640x480 ; Enable VGA mode for a better display.
;CALL SETVGAMODE1
LD A, TZSVC_CMD_CPU_SETT80 ; We need to ask the K64F to switch to the T80 as it may involve loading of ROMS.
CALL SVC_CMD
OR A
JP NZ,SETT80ERR
RET
; Method to configure the hardware to use the original Z80 CPU installed on the tranZPUter board.
;
SETZ80: IN A,(CPUINFO)
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JP NZ,SOFTCPUERR
CALL SETVMODE1 ; Turn off VGA mode, return to default MZ video.
LD A, TZSVC_CMD_CPU_SETZ80
CALL SVC_CMD
OR A
JP NZ,SETZ80ERR
RET
; Method to configure the hardware to use the ZPU Evolution CPU instantiated in the FPGA.
;
SETZPUEVO: IN A,(CPUINFO)
LD C,A
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JP NZ,SOFTCPUERR
LD A,C
AND CPUMODE_IS_ZPU_EVO
JP Z,NOZPUERR
LD L,VMMODE_VGA_640x480 ; Enable VGA mode for a better display.
CALL SETVGAMODE1
LD A, TZSVC_CMD_CPU_SETZPUEVO ; We need to ask the K64F to switch to the ZPU Evo as it may involve loading of ROMS.
CALL SVC_CMD
OR A
JP NZ,SETZPUERR
HALT ; ZPU will take over so stop the Z80 from further processing.
;----------------------------------------------
; Hardware Emulation Mode Activation Routines.
;----------------------------------------------
SETMZ80K: LD D, TZSVC_CMD_EMU_SETMZ80K ; We need to ask the K64F to switch to the Sharp MZ80K emulation as it involves loading ROMS.
JR SETEMUMZ
SETMZ80C: LD D, TZSVC_CMD_EMU_SETMZ80C
JR SETEMUMZ
SETMZ1200: LD D, TZSVC_CMD_EMU_SETMZ1200
JR SETEMUMZ
SETMZ80A: LD D, TZSVC_CMD_EMU_SETMZ80A
JR SETEMUMZ
SETMZ700: LD D, TZSVC_CMD_EMU_SETMZ700
JR SETEMUMZ
SETMZ1500: LD D, TZSVC_CMD_EMU_SETMZ1500
JR SETEMUMZ
SETMZ800: LD D, TZSVC_CMD_EMU_SETMZ800
JR SETEMUMZ
SETMZ80B: LD D, TZSVC_CMD_EMU_SETMZ80B
JR SETEMUMZ
SETMZ2000: LD D, TZSVC_CMD_EMU_SETMZ2000
JR SETEMUMZ
SETMZ2200: LD D, TZSVC_CMD_EMU_SETMZ2200
JR SETEMUMZ
SETMZ2500: LD D, TZSVC_CMD_EMU_SETMZ2500
JR SETEMUMZ
;
; General function to determine if the emulator MZ hardware is present and activate it. Activation requires making a request to the
; I/O processor as it needs to load up the correct BIOS etc prior to activating the emulation.
;
SETEMUMZ: IN A,(CPUINFO) ; Verify that the FPGA has emuMZ capabilities.
LD C,A
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JR NZ,SOFTCPUERR
LD A,C
AND CPUMODE_IS_EMU_MZ
JR Z,NOEMUERR
LD L,VMMODE_VGA_640x480 ; Enable VGA mode for a better display.
CALL SETVGAMODE1
;
PUSH DE ; Setup the initial video mode based on the required emulation.
LD A,D
SUB TZSVC_CMD_EMU_SETMZ80K
LD L,A
LD H,0
CALL SETVMODE0
POP DE
;
LD A, D ; Load up the required emulation mode.
CALL SVC_CMD
OR A
JR NZ,SETT80ERR
HALT
; Simple routine to clear screen or attributes.
CLR8: LD BC,00800H
PUSH DE
LD D,A
CLR8_1: LD (HL),D
INC HL
DEC BC
LD A,B
OR C
JR NZ,CLR8_1
POP DE
RET
;
; Message addresses are in Bank2.
;
NOFPGAERR: LD DE,MSGNOFPGA
JR BADNUM2
SETFREQERR: LD DE,MSGFREQERR
JR BADNUM2
SETT80ERR: LD DE,MSGT80ERR
JR BADNUM2
SETZ80ERR: LD DE,MSGZ80ERR
JR BADNUM2
SETZPUERR: LD DE,MSGZPUERR
JR BADNUM2
SOFTCPUERR: LD DE,MSGNOSOFTCPU
JR BADNUM2
NOT80ERR: LD DE,MSGNOT80CPU
JR BADNUM2
NOZPUERR: LD DE,MSGNOZPUCPU
JR BADNUM2
NOEMUERR: LD DE,MSGNOEMU
JR BADNUM2
BADNUMERR: LD DE,MSGBADNUM
BADNUM2: CALL ?PRINTMSG
RET
;-------------------------------------------------------------------------------
; END OF ADDITIONAL TZFS COMMANDS
;-------------------------------------------------------------------------------
; The FDC controller uses it's busy/wait signal as a ROM address line input, this
; causes a jump in the code dependent on the signal status. It gets around the 2MHz Z80 not being quick
; enough to process the signal by polling.
ALIGN_NOPS FDCJMP1
ORG FDCJMP1
FDCJMPL4: JP (IX)
; The FDC controller uses it's busy/wait signal as a ROM address line input, this
; causes a jump in the code dependent on the signal status. It gets around the 2MHz Z80 not being quick
; enough to process the signal by polling.
ALIGN_NOPS FDCJMP2
ORG FDCJMP2
FDCJMPH4: JP (IY)
; Ensure we fill the entire 4K by padding with FF's.
;
ALIGN_NOPS 10000H

BIN
software/roms/1Z001M.rom vendored Normal file

Binary file not shown.

BIN
software/roms/KUMA80.BIN vendored Normal file

Binary file not shown.

BIN
software/roms/monitor_1z-013a-km.rom vendored Normal file

Binary file not shown.

BIN
software/roms/monitor_1z-013a.rom vendored Normal file

Binary file not shown.

BIN
software/roms/monitor_80c_1z-013a-km.rom vendored Normal file

Binary file not shown.

BIN
software/roms/monitor_80c_1z-013a.rom vendored Normal file

Binary file not shown.

BIN
software/roms/monitor_80c_sa1510.rom vendored Normal file

Binary file not shown.

BIN
software/roms/monitor_sa1510.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz2000_basic_1z001.rom vendored Executable file

Binary file not shown.

BIN
software/roms/mz2000_basic_1z002.rom vendored Executable file

Binary file not shown.

BIN
software/roms/mz2000_ipl_fusionx.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz2000_ipl_original.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz2000_ipl_tzpu.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz2000_mon_1z001m.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz800_1z_013b.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz800_9z_504m.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz800_iocs.rom vendored Normal file

Binary file not shown.

BIN
software/roms/mz800_ipl.rom vendored Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More