"MTX Plus+" Speculator+
Introduction
Tony Brewer developed a product called
Speculator
for the original MTX computer, it allowed an MTX512 or RS128 to
emulate a
Sinclair ZX Spectrum sufficiently to run a limited number of
Spectrum games on the MTX. A version of Speculator was also
released for the Tatung Einstein which supported a larger number
of games, loaded from disk.
To use the MTX version, the user first loaded the Speculator
tape which contained the Spectrum emulation code and presented a
menu of 20 games that the user could load from the
original Spectrum tape and play on the MTX. (My
Speculator page
describes Speculator in more detail.)
With assistance from Tony,
Andy Key has added Speculator support to
MEMU, his
excellent Memotech MTX emulator.
Tony has now helped us to integrate Speculator with MTXPlus+.
The Memotech version of Speculator used a couple of 74 series
TTL chips, a couple of PLDs and a 2K SRAM, which were used to
emulate the Spectrum keyboard.
With the extra resources that MTXPlus+ has available, the
MTXPlus+ version does not require additional hardware and has a
number of enhancements over the Spectrum version :-
- Faster operation
- Optimised for running at 8Mhz
- Uses fast paging of MTXPlus+ extended RAM
- Compact Flash media support
- Uses a copy of the actual Spectrum ROM
With it's significant improvements over the original, and in
line with the MTXPlus+ system name, Spectrum support in MTXPlus+
has been christened Speculator+.
MTX Speculator
In the ZX Spectrum, the Z80 CPU was clocked at 3.5MHz, in the
MTX computer, the clock speed was 4MHz, although only slightly
faster, the design of Speculator allowed emulated Spectrum games
to run at an acceptable speed.
Running on the MTX, Speculator had to work its magic in
the 64k of RAM available in an MTX512. The Speculator code moved
16kb of banked RAM from its usual position at Page 1 (8000h to BFFFh) of the MTX memory map to Page 0 (0000h to 3FFFh) in
RELCPMH=1 mode, i.e., paging out the MTX ROMs and making a full
64kb of contiguous RAM available.
Most Spectrum games bypassed the Sinclair ROM and used very
few of the native ROM routines, so Speculator did not need to
emulate most of the Sinclair ROM. A very few functions, such as
the Clear Screen (CLS) function were needed, and since
Speculator could not use any copyrighted Sinclair code, the
first 16kb of RAM had to have an equivalent function located at
the same address as the original so that the game could find the
code in the emulated ROM.
ZX Spectrum Memory Map
Address Range |
Contents |
0000h -
3FFFh |
ZX Spectrum
ROM memory range |
3D00h - 3FFFh |
Spectrum
character shape table |
4000h
- 57FFh* |
Spectrum
display file |
5800h -
5AFFh* |
Spectrum
colour attributes |
5B00h
- 5BFFh |
(printer
buffer) |
5C00h -
5CBFh |
Spectrum
System Variables |
5CC0h -
5CCAh |
(reserved) |
5CCBh -
FFFFh |
Free for
Spectrum game code |
2000h -
5CFFh |
Speculator
Supervisory code |
(For more details of
the Spectrum ROM, see my
ZX
Spectrum page) |
* The Spectrum's screen characters and colour attributes are
stored in RAM and a major element of the Speculator code was to
move the screen data between the system RAM and the Video RAM
used by the MTX's TMS 99xx VDP through the VDP I/O ports.
Whilst the Spectrum and MTX video resolution's were the same,
at 256x192 pixels, the MTX VDP had better colour capabilities
and required more information to be stored in VRAM than in the
Spectrum's memory mapped display area. Speculator had to move
1B00h bytes into the 4000h bytes of MTX VRAM, ideally, this
would have been done every time that the Spectrum screen was
updated, but the overhead of doing this would have been too
great to allow acceptable game play.
Instead, Speculator used some clever tricks to optimise the
screen updates using interrupts. The Z80 interrupt on the
Spectrum is triggered at the start of the screen refresh
vertical blanking period which takes place at 50Hz, it was
possible to update 1/6th of the screen in each interrupt cycle.
Depending on where more screen activity took place in a given
game, Speculator could update some areas of the screen more
often than others. For example, most of the action in
Starion takes place in the top two thirds of the display, so
Speculator refreshes the bottom third at a lower frequency,
allowing the rest of the screen to run close to the speed of the
original.
Colour updates were optimised too, the 8 Spectrum colours
were mapped to the closest colours in the TMS VDP palette of 16,
but only those attributes that had changed were updated in the
VDP's VRAM.
MTXPlus+ Speculator+
When Speculator was released, it was not possible to legally
copy the Spectrum ROM or to include portions of it in
Speculator, however,
Sinclair Research sold the rights to their computer
products, including the Spectrum, to Amstrad in 1995. Amstrad
still owns the copyright for the Spectrum ROMs, but since 1999,
has allowed free copying and distribution of the ROMs. For
details,
see this record of a post on the comp.sys.sinclair
forum archived on the
World of Spectrum website. This means that Speculator+
can legally use a copy of the original ROM and doesn't need to
have code to mimic the original Spectrum code.
As with the original Speculator, the system runs with the
normal MTX ROMs paged out and the full 64k Z80 address space
taken up with RAM, with the lower 16k of RAM being occupied by
Spectrum ROM code (except during NMI periods).
Like the original, Speculator+ needs to convert
Spectrum hardware specific data in RAM, such as screen data and
attributes, into their MTX equivalent and it does this in a
similar way to the original, using the Z80
NMI function. In Speculator+, this is done by
paging out the Spectrum ROM and paging in the Speculator+
specific code during the NMI period.
Since Speculator+ now includes a copy of the
Spectrum ROM in RAM space, an additional measure is needed to
guard against one of the "tricks" used by Spectrum programmers
corrupting the "ROM" data. As the Spectrum memory map (above)
shows, the display data file is immediately after the 16k ROM.
Some Spectrum code writes to addresses below 4000H when updating
the top-left of the display, safe in the knowledge that the ROM
cannot be altered. In other words the programmers didn't bother
with rigorous boundary checking when it didn't really matter. To
prevent data writes to the ROM when it is in MTXPlus+ RAM,
Speculator+ write protects the lower 16k of RAM,
except during the NMI routine. This is done by putting the RAM
WR line under the control of
the Speculator+ CPLD, rather than the CPU, and conditioning the
write signal based on the target memory address when Speculator+
is running.
Memory Management
Speculator+ uses the MTX/MTXPlus+
memory paging system to control its operation, a quick overview
of the MTX Page Port will help understanding of how this works.
More details of MTXPlus+ memory paging can be found
on this page.
Output port 0 is the MTX Page Port, this 8 bit port is used
to switch the system between ROM enabled mode and RAM only mode
and to select the ROM or RAM page used for memory access.
MTXPlus+
Page Port |
Bit |
Mnemonic |
Bit
Mapping |
Description |
|
|
|
|
7 |
RELCPMH |
|
ROM/RAM Mode Select (0 = ROM
Enabled) |
6 |
R2 |
|
ROM Page Select bits |
5 |
R1 |
Allows selection of up to 8
paged ROMS |
4 |
R0 |
|
3 |
P3 |
|
RAM Page Select bits |
2 |
P2 |
Allows selection of up to 16
pages of paged RAM |
1 |
P1 |
(Each RAM page is 32kb) |
0 |
P0 |
|
Without paging, Z80 Address bits A0 to A15
can address up to 215 bytes i.e., 64kb of memory.
Similar to the original MTX, MTXPlus+ supports up to 512kb of
RAM using paging, up to 16 pages, each of size 32kb, can be
paged into the Z80's address space. Address bits A0
to A13 can address up to 213, i.e., 16k
memory locations; A14 and A15 are used to
point to the location of the 16kb block in the memory map. When
A14 and A15 are set, the common 16kb block
is selected, selection of other pages in the RAM is done using A14,
A15 and the Page Port RAM bits to map the extended
RAM into the 16 bit address space.
Using the expanded memory of MTXPlus+, Speculator+ has access
to a protected block of 64kb of RAM that was not available to
the original Speculator. This block of RAM can be accessed in
both ROM and RAM modes (RELCPMH = 0 or 1) using appropriate page
port values.
When MTXPlus+ starts, it does
so in ROM mode (RELCPMH=0) and 4x16kb blocks of high
memory are reserved for Speculator+ use by placing them
above the empty block in Page 13 (D) of the memory map.
When MTXPlus+ is running under control of the ROMs,
these hidden pages are not used and just reduce the apparent total RAM to 448kb. |
|
A 512kb RAM uses 18 address lines to access the 218
memory addresses, the MTXPlus+ address decoding logic sets the
values of the address lines to target the appropriate block in
the 512kb RAM. The following table, extracted from the memory
decode logic, shows the paged RAM blocks used by Speculator+.
Page |
RAM
select bits |
Page |
Memory |
Block |
High Address Lines |
Port |
A14 |
A15 |
P0 |
P1 |
P2 |
P3 |
1 |
1 |
- |
- |
- |
- |
0 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
|
|
Range |
Number |
A18 |
A17 |
A16 |
A15 |
A14 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
|
All |
Common |
48-64k |
31 |
0E |
E |
32-48k |
28 |
0F |
F |
32-48k |
30 |
0E |
E |
16-32k |
29 |
0E |
E |
32-48k |
28 |
0F |
F |
16-32k |
27 |
8E |
E |
0-16k |
28 |
8E |
E |
32-48k |
30 |
8F |
F |
32-48k |
30 |
8E |
E |
0-16k |
28 |
8F |
F |
0-16k |
29 |
8E |
E |
16-32k |
27 |
8F |
F |
16-32k |
27 |
In summary, the
table below shows which blocks are active based on the
Page Port value output
Page Port |
0-16k |
16-32k |
32-48k |
48-64k |
0E |
-- |
29 |
28 |
31 |
0F |
-- |
27 |
30 |
31 |
8E |
28 |
27 |
30 |
31 |
8F |
29 |
27 |
30 |
31 |
|
In RAM only mode (RELCPMH=1), the MTX
pages memory in 48k blocks and by careful positioning of
the memory pages used by Speculator+, RAM usage could be
optimised. As the table shows, some of the memory pages
have been made to appear in different Page Port
configurations. |
When Speculator+
is running, the contents of these reserved locations is
as shown in the table.
Block number 31 is the
common block of RAM, from 48k to 64k, visible in all
memory modes. When Speculator+ is running, the upper 16kb
of Spectrum RAM (32-48k) is mapped into this space. |
Block |
Contents |
27 |
Spectrum RAM (0-16k) |
28 |
Spectrum ROM |
29 |
Speculator+ Code |
30 |
Spectrum RAM (16-32k) |
31 |
Spectrum RAM (32-48k) |
|
When the system is
in ROM mode (RELCPMH=0) and the value "0E" is written to
the Page Port, pages 28 and 29 are both visible,
allowing the Spectrum "ROM" and Speculator+
NMI "ROM" to be loaded from CF. |
When the system
is switched to RAM only mode (RELCPMH=1), the memory
memory map is changed to duplicate two of the Speculator
RAM blocks, making them appear twice in the address
space, effectively meaning that the 48k of Spectrum RAM
is common when the Page Port is switched between "8E"
(Spectrum "ROM") and "8F" (Speculator+
"ROM"). |
|
The NMI "ROM" is
paged in and out to refresh the Spectrum display, the
same block of RAM used to replicate the Spectrum 48k RAM
is visible to both the Spectrum "ROM" and the NMI
"ROM".
When the Spectrum "ROM" is
switched in, the lower 16k of RAM is write protected to
simulate the effect of an actual ROM being present in
this address range. |
|
|
|
|
|
When the Z80 NMI pin goes
low, the CPLD has the same effect as writing "8F" to the Page
Port, i.e., block 29 (containing the Speculator+
"ROM") replaces block 28 (the Spectrum ROM) in the lower 16k of
RAM and the write protection is removed from this address range.
When the Z80 NMI pin goes
low, the CPU will execute the instruction at address 0066h,
which will be the Speculator+ NMI code to update the
Spectrum screen, i,e., the MTX VRAM is updated from the Spectrum
screen data starting at address 4000h in the 16-32k block of RAM
in block 27.
I/O Ports
Speculator and Speculator+ need to emulate a few
Spectrum I/O ports to be able to interface with the Spectrum
program, these are summarised in the table below :
XX = Original Spectrum
48k port
XX
= Speculator+ port
Port |
I/O |
Function |
Bit |
|
Function |
|
|
|
|
|
|
1F |
I |
Read Joystick |
0 |
Right |
Read Kempston Joystick switch |
|
|
|
1 |
Left |
Read Kempston Joystick switch |
|
|
|
2 |
Down |
Read Kempston Joystick switch |
|
|
|
3 |
Up |
Read Kempston Joystick switch |
|
|
|
4 |
Fire |
Read Kempston Joystick switch |
|
|
|
5-7 |
Unused |
|
1F |
O |
Write Joystick |
0 |
Write the
emulated Kempston joystick values.
Speculator
writes to this port to send the MTX keyboard or joystick
signals to the Kempston joystick port. |
|
|
|
1 |
|
|
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5-7 |
|
|
|
|
7E |
O |
Write keyboard |
0 |
Write the
emulated Spectrum keyboard values, the first low bit in
A15-A8 selects the row.
This port is used to
convert the MTX key presses to the values expected by
the Spectrum program. See Port FE below for details of
how the Spectrum key scanning works.
Unused |
|
|
|
1 |
|
|
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5-7 |
|
|
|
|
FE |
I |
Read
keyboard |
|
A "0" on one of Address lines A15..A8
selects a particular half row of 5 keys to be read from
I/O port FE. Each column in the table below corresponds
to the relevant address line being low while the others
are high, e.g., when A15 is set low, the address word
would be "11111110", i.e., "FE", selecting half row
number 7. A "0" in one of the 5 lowest bits means
that the corresponding key has been pressed. |
|
|
|
|
FE |
FD |
FB |
F7 |
EF |
DF |
BF |
7F |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
shift |
A |
Q |
1 |
0 |
P |
enter |
space |
Z |
S |
W |
2 |
9 |
O |
L |
sym
shft |
X |
D |
E |
3 |
8 |
I |
K |
M |
C |
F |
R |
4 |
7 |
U |
J |
N |
V |
G |
T |
5 |
6 |
Y |
H |
B |
|
FE |
I |
(Read I/O) |
5-7 |
Unused |
(In Speculator+) |
FE |
O |
Write border |
0 |
BORDER |
Blue |
|
|
|
1 |
BORDER |
Red |
|
|
|
2 |
BORDER |
Green |
|
|
|
3 |
(Mike) |
0 = Activate Mike output ***
Not used *** |
|
|
|
4 |
(Ear) |
1 = Activate Ear output *** Not
used *** |
|
|
|
5-7 |
- |
Unused |
|
|
|
|
|
|
FF |
O |
NMI Control |
0 |
NMI_EN |
0 = Disable, 1 = Enable |
|
|
|
1 |
NMI_SEL |
0 = Delayed, 1 =
Immediate *** Not used *** |
|
|
|
2 |
ZX_MODE |
0 = Lower 16K R/W, 1 = Lower 16K R/O |
|
|
|
3-7 |
- |
Used for CPU clock rate
selection |
|