summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/timex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/timex.cpp')
-rw-r--r--src/mame/drivers/timex.cpp782
1 files changed, 782 insertions, 0 deletions
diff --git a/src/mame/drivers/timex.cpp b/src/mame/drivers/timex.cpp
new file mode 100644
index 00000000000..ad12202fae0
--- /dev/null
+++ b/src/mame/drivers/timex.cpp
@@ -0,0 +1,782 @@
+// license:GPL-2.0+
+// copyright-holders:Kevin Thacker
+/***************************************************************************
+
+ NOTE: ****** Specbusy: press N, R, or E to boot *************
+
+
+ Spectrum/Inves/TK90X etc. memory map:
+
+ CPU:
+ 0000-3fff ROM
+ 4000-ffff RAM
+
+ Spectrum 128/+2/+2a/+3 memory map:
+
+ CPU:
+ 0000-3fff Banked ROM/RAM (banked rom only on 128/+2)
+ 4000-7fff Banked RAM
+ 8000-bfff Banked RAM
+ c000-ffff Banked RAM
+
+ TS2068 memory map: (Can't have both EXROM and DOCK active)
+ The 8K EXROM can be loaded into multiple pages.
+
+ CPU:
+ 0000-1fff ROM / EXROM / DOCK (Cartridge)
+ 2000-3fff ROM / EXROM / DOCK
+ 4000-5fff \
+ 6000-7fff \
+ 8000-9fff |- RAM / EXROM / DOCK
+ a000-bfff |
+ c000-dfff /
+ e000-ffff /
+
+
+Interrupts:
+
+Changes:
+
+29/1/2000 KT - Implemented initial +3 emulation.
+30/1/2000 KT - Improved input port decoding for reading and therefore
+ correct keyboard handling for Spectrum and +3.
+31/1/2000 KT - Implemented buzzer sound for Spectrum and +3.
+ Implementation copied from Paul Daniel's Jupiter driver.
+ Fixed screen display problems with dirty chars.
+ Added support to load .Z80 snapshots. 48k support so far.
+13/2/2000 KT - Added Interface II, Kempston, Fuller and Mikrogen
+ joystick support.
+17/2/2000 DJR - Added full key descriptions and Spectrum+ keys.
+ Fixed Spectrum +3 keyboard problems.
+17/2/2000 KT - Added tape loading from WAV/Changed from DAC to generic
+ speaker code.
+18/2/2000 KT - Added tape saving to WAV.
+27/2/2000 KT - Took DJR's changes and added my changes.
+27/2/2000 KT - Added disk image support to Spectrum +3 driver.
+27/2/2000 KT - Added joystick I/O code to the Spectrum +3 I/O handler.
+14/3/2000 DJR - Tape handling dipswitch.
+26/3/2000 DJR - Snapshot files are now classifed as snapshots not
+ cartridges.
+04/4/2000 DJR - Spectrum 128 / +2 Support.
+13/4/2000 DJR - +4 Support (unofficial 48K hack).
+13/4/2000 DJR - +2a Support (rom also used in +3 models).
+13/4/2000 DJR - TK90X, TK95 and Inves support (48K clones).
+21/4/2000 DJR - TS2068 and TC2048 support (TC2048 Supports extra video
+ modes but doesn't have bank switching or sound chip).
+09/5/2000 DJR - Spectrum +2 (France, Spain), +3 (Spain).
+17/5/2000 DJR - Dipswitch to enable/disable disk drives on +3 and clones.
+27/6/2000 DJR - Changed 128K/+3 port decoding (sound now works in Zub 128K).
+06/8/2000 DJR - Fixed +3 Floppy support
+10/2/2001 KT - Re-arranged code and split into each model emulated.
+ Code is split into 48k, 128k, +3, tc2048 and ts2048
+ segments. 128k uses some of the functions in 48k, +3
+ uses some functions in 128, and tc2048/ts2048 use some
+ of the functions in 48k. The code has been arranged so
+ these functions come in some kind of "override" order,
+ read functions changed to use READ8_HANDLER and write
+ functions changed to use WRITE8_HANDLER.
+ Added Scorpion256 preliminary.
+18/6/2001 DJR - Added support for Interface 2 cartridges.
+xx/xx/2001 KS - TS-2068 sound fixed.
+ Added support for DOCK cartridges for TS-2068.
+ Added Spectrum 48k Psycho modified rom driver.
+ Added UK-2086 driver.
+23/12/2001 KS - 48k machines are now able to run code in screen memory.
+ Programs which keep their code in screen memory
+ like monitors, tape copiers, decrunchers, etc.
+ works now.
+ Fixed problem with interrupt vector set to 0xffff (much
+ more 128k games works now).
+ A useful used trick on the Spectrum is to set
+ interrupt vector to 0xffff (using the table
+ which contain 0xff's) and put a byte 0x18 hex,
+ the opcode for JR, at this address. The first
+ byte of the ROM is a 0xf3 (DI), so the JR will
+ jump to 0xfff4, where a long JP to the actual
+ interrupt routine is put. Due to unideal
+ bankswitching in MAME this JP were to 0001 what
+ causes Spectrum to reset. Fixing this problem
+ made much more software runing (i.e. Paperboy).
+ Corrected frames per second value for 48k and 128k
+ Sincalir machines.
+ There are 50.08 frames per second for Spectrum
+ 48k what gives 69888 cycles for each frame and
+ 50.021 for Spectrum 128/+2/+2A/+3 what gives
+ 70908 cycles for each frame.
+ Remaped some Spectrum+ keys.
+ Presing F3 to reset was seting 0xf7 on keyboard
+ input port. Problem occurred for snapshots of
+ some programms where it was readed as pressing
+ key 4 (which is exit in Tapecopy by R. Dannhoefer
+ for example).
+ Added support to load .SP snapshots.
+ Added .BLK tape images support.
+ .BLK files are identical to .TAP ones, extension
+ is an only difference.
+08/03/2002 KS - #FF port emulation added.
+ Arkanoid works now, but is not playable due to
+ completly messed timings.
+
+Initialisation values used when determining which model is being emulated:
+ 48K Spectrum doesn't use either port.
+ 128K/+2 Bank switches with port 7ffd only.
+ +3/+2a Bank switches with both ports.
+
+Notes:
+ 1. No contented memory.
+ 2. No hi-res colour effects (need contended memory first for accurate timing).
+ 3. Multiface 1 and Interface 1 not supported.
+ 4. Horace and the Spiders cartridge doesn't run properly.
+ 5. Tape images not supported:
+ .TZX, .SPC, .ITM, .PAN, .TAP(Warajevo), .VOC, .ZXS.
+ 6. Snapshot images not supported:
+ .ACH, .PRG, .RAW, .SEM, .SIT, .SNX, .ZX, .ZXS, .ZX82.
+ 7. 128K emulation is not perfect - the 128K machines crash and hang while
+ running quite a lot of games.
+ 8. Disk errors occur on some +3 games.
+ 9. Video hardware of all machines is timed incorrectly.
+10. EXROM and HOME cartridges are not emulated.
+11. The TK90X and TK95 roms output 0 to port #df on start up.
+12. The purpose of this port is unknown (probably display mode as TS2068) and
+ thus is not emulated.
+
+Very detailed infos about the ZX Spectrum +3e can be found at
+
+http://www.z88forever.org.uk/zxplus3e/
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cpu/z80/z80.h"
+#include "includes/spectrum.h"
+#include "imagedev/snapquik.h"
+#include "imagedev/cassette.h"
+#include "sound/speaker.h"
+#include "sound/ay8910.h"
+#include "formats/tzx_cas.h"
+#include "machine/spec_snqk.h"
+#include "machine/beta.h"
+#include "machine/ram.h"
+#include "softlist.h"
+
+/****************************************************************************************************/
+/* TS2048 specific functions */
+
+
+READ8_MEMBER( spectrum_state::ts2068_port_f4_r )
+{
+ return m_port_f4_data;
+}
+
+WRITE8_MEMBER( spectrum_state::ts2068_port_f4_w )
+{
+ m_port_f4_data = data;
+ ts2068_update_memory();
+}
+
+READ8_MEMBER( spectrum_state::ts2068_port_ff_r )
+{
+ return m_port_ff_data;
+}
+
+WRITE8_MEMBER( spectrum_state::ts2068_port_ff_w )
+{
+ /* Bits 0-2 Video Mode Select
+ Bits 3-5 64 column mode ink/paper selection
+ (See ts2068_vh_screenrefresh for more info)
+ Bit 6 17ms Interrupt Inhibit
+ Bit 7 Cartridge (0) / EXROM (1) select
+ */
+ m_port_ff_data = data;
+ ts2068_update_memory();
+ logerror("Port %04x write %02x\n", offset, data);
+}
+
+/*******************************************************************
+ *
+ * Bank switch between the 3 internal memory banks HOME, EXROM
+ * and DOCK (Cartridges). The HOME bank contains 16K ROM in the
+ * 0-16K area and 48K RAM fills the rest. The EXROM contains 8K
+ * ROM and can appear in every 8K segment (ie 0-8K, 8-16K etc).
+ * The DOCK is empty and is meant to be occupied by cartridges
+ * you can plug into the cartridge dock of the 2068.
+ *
+ * The address space is divided into 8 8K chunks. Bit 0 of port
+ * #f4 corresponds to the 0-8K chunk, bit 1 to the 8-16K chunk
+ * etc. If the bit is 0 then the chunk is controlled by the HOME
+ * bank. If the bit is 1 then the chunk is controlled by either
+ * the DOCK or EXROM depending on bit 7 of port #ff. Note this
+ * means that that the Z80 can't see chunks of the EXROM and DOCK
+ * at the same time.
+ *
+ *******************************************************************/
+void spectrum_state::ts2068_update_memory()
+{
+ UINT8 *messram = m_ram->pointer();
+ address_space &space = m_maincpu->space(AS_PROGRAM);
+ UINT8 *DOCK = m_dock_crt->base();
+ UINT8 *ExROM = memregion("maincpu")->base() + 0x014000;
+ UINT8 *ChosenROM;
+
+ if (m_port_f4_data & 0x01)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ space.install_read_bank(0x0000, 0x1fff, "bank1");
+ space.unmap_write(0x0000, 0x1fff);
+ membank("bank1")->set_base(ExROM);
+ logerror("0000-1fff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank1")->set_base(DOCK);
+ space.install_read_bank(0x0000, 0x1fff, "bank1");
+ if (m_ram_chunks & 0x01)
+ space.install_write_bank(0x0000, 0x1fff, "bank9");
+ else
+ space.unmap_write(0x0000, 0x1fff);
+
+
+ }
+ else
+ {
+ space.nop_read(0x0000, 0x1fff);
+ space.unmap_write(0x0000, 0x1fff);
+ }
+ logerror("0000-1fff Cartridge\n");
+ }
+ }
+ else
+ {
+ ChosenROM = memregion("maincpu")->base() + 0x010000;
+ membank("bank1")->set_base(ChosenROM);
+ space.install_read_bank(0x0000, 0x1fff, "bank1");
+ space.unmap_write(0x0000, 0x1fff);
+ logerror("0000-1fff HOME\n");
+ }
+
+ if (m_port_f4_data & 0x02)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ membank("bank2")->set_base(ExROM);
+ space.install_read_bank(0x2000, 0x3fff, "bank2");
+ space.unmap_write(0x2000, 0x3fff);
+ logerror("2000-3fff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank2")->set_base(DOCK+0x2000);
+ space.install_read_bank(0x2000, 0x3fff, "bank2");
+ if (m_ram_chunks & 0x02)
+ space.install_write_bank(0x2000, 0x3fff, "bank10");
+ else
+ space.unmap_write(0x2000, 0x3fff);
+
+ }
+ else
+ {
+ space.nop_read(0x2000, 0x3fff);
+ space.unmap_write(0x2000, 0x3fff);
+ }
+ logerror("2000-3fff Cartridge\n");
+ }
+ }
+ else
+ {
+ ChosenROM = memregion("maincpu")->base() + 0x012000;
+ membank("bank2")->set_base(ChosenROM);
+ space.install_read_bank(0x2000, 0x3fff, "bank2");
+ space.unmap_write(0x2000, 0x3fff);
+ logerror("2000-3fff HOME\n");
+ }
+
+ if (m_port_f4_data & 0x04)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ membank("bank3")->set_base(ExROM);
+ space.install_read_bank(0x4000, 0x5fff, "bank3");
+ space.unmap_write(0x4000, 0x5fff);
+ logerror("4000-5fff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank3")->set_base(DOCK+0x4000);
+ space.install_read_bank(0x4000, 0x5fff, "bank3");
+ if (m_ram_chunks & 0x04)
+ space.install_write_bank(0x4000, 0x5fff, "bank11");
+ else
+ space.unmap_write(0x4000, 0x5fff);
+ }
+ else
+ {
+ space.nop_read(0x4000, 0x5fff);
+ space.unmap_write(0x4000, 0x5fff);
+ }
+ logerror("4000-5fff Cartridge\n");
+ }
+ }
+ else
+ {
+ membank("bank3")->set_base(messram);
+ membank("bank11")->set_base(messram);
+ space.install_read_bank(0x4000, 0x5fff, "bank3");
+ space.install_write_bank(0x4000, 0x5fff, "bank11");
+ logerror("4000-5fff RAM\n");
+ }
+
+ if (m_port_f4_data & 0x08)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ membank("bank4")->set_base(ExROM);
+ space.install_read_bank(0x6000, 0x7fff, "bank4");
+ space.unmap_write(0x6000, 0x7fff);
+ logerror("6000-7fff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank4")->set_base(DOCK+0x6000);
+ space.install_read_bank(0x6000, 0x7fff, "bank4");
+ if (m_ram_chunks & 0x08)
+ space.install_write_bank(0x6000, 0x7fff, "bank12");
+ else
+ space.unmap_write(0x6000, 0x7fff);
+ }
+ else
+ {
+ space.nop_read(0x6000, 0x7fff);
+ space.unmap_write(0x6000, 0x7fff);
+ }
+ logerror("6000-7fff Cartridge\n");
+ }
+ }
+ else
+ {
+ membank("bank4")->set_base(messram + 0x2000);
+ membank("bank12")->set_base(messram + 0x2000);
+ space.install_read_bank(0x6000, 0x7fff, "bank4");
+ space.install_write_bank(0x6000, 0x7fff, "bank12");
+ logerror("6000-7fff RAM\n");
+ }
+
+ if (m_port_f4_data & 0x10)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ membank("bank5")->set_base(ExROM);
+ space.install_read_bank(0x8000, 0x9fff, "bank5");
+ space.unmap_write(0x8000, 0x9fff);
+ logerror("8000-9fff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank5")->set_base(DOCK+0x8000);
+ space.install_read_bank(0x8000, 0x9fff,"bank5");
+ if (m_ram_chunks & 0x10)
+ space.install_write_bank(0x8000, 0x9fff,"bank13");
+ else
+ space.unmap_write(0x8000, 0x9fff);
+ }
+ else
+ {
+ space.nop_read(0x8000, 0x9fff);
+ space.unmap_write(0x8000, 0x9fff);
+ }
+ logerror("8000-9fff Cartridge\n");
+ }
+ }
+ else
+ {
+ membank("bank5")->set_base(messram + 0x4000);
+ membank("bank13")->set_base(messram + 0x4000);
+ space.install_read_bank(0x8000, 0x9fff,"bank5");
+ space.install_write_bank(0x8000, 0x9fff,"bank13");
+ logerror("8000-9fff RAM\n");
+ }
+
+ if (m_port_f4_data & 0x20)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ membank("bank6")->set_base(ExROM);
+ space.install_read_bank(0xa000, 0xbfff, "bank6");
+ space.unmap_write(0xa000, 0xbfff);
+ logerror("a000-bfff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank6")->set_base(DOCK+0xa000);
+ space.install_read_bank(0xa000, 0xbfff, "bank6");
+ if (m_ram_chunks & 0x20)
+ space.install_write_bank(0xa000, 0xbfff, "bank14");
+ else
+ space.unmap_write(0xa000, 0xbfff);
+
+ }
+ else
+ {
+ space.nop_read(0xa000, 0xbfff);
+ space.unmap_write(0xa000, 0xbfff);
+ }
+ logerror("a000-bfff Cartridge\n");
+ }
+ }
+ else
+ {
+ membank("bank6")->set_base(messram + 0x6000);
+ membank("bank14")->set_base(messram + 0x6000);
+ space.install_read_bank(0xa000, 0xbfff, "bank6");
+ space.install_write_bank(0xa000, 0xbfff, "bank14");
+ logerror("a000-bfff RAM\n");
+ }
+
+ if (m_port_f4_data & 0x40)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ membank("bank7")->set_base(ExROM);
+ space.install_read_bank(0xc000, 0xdfff, "bank7");
+ space.unmap_write(0xc000, 0xdfff);
+ logerror("c000-dfff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank7")->set_base(DOCK+0xc000);
+ space.install_read_bank(0xc000, 0xdfff, "bank7");
+ if (m_ram_chunks & 0x40)
+ space.install_write_bank(0xc000, 0xdfff, "bank15");
+ else
+ space.unmap_write(0xc000, 0xdfff);
+ }
+ else
+ {
+ space.nop_read(0xc000, 0xdfff);
+ space.unmap_write(0xc000, 0xdfff);
+ }
+ logerror("c000-dfff Cartridge\n");
+ }
+ }
+ else
+ {
+ membank("bank7")->set_base(messram + 0x8000);
+ membank("bank15")->set_base(messram + 0x8000);
+ space.install_read_bank(0xc000, 0xdfff, "bank7");
+ space.install_write_bank(0xc000, 0xdfff, "bank15");
+ logerror("c000-dfff RAM\n");
+ }
+
+ if (m_port_f4_data & 0x80)
+ {
+ if (m_port_ff_data & 0x80)
+ {
+ membank("bank8")->set_base(ExROM);
+ space.install_read_bank(0xe000, 0xffff, "bank8");
+ space.unmap_write(0xe000, 0xffff);
+ logerror("e000-ffff EXROM\n");
+ }
+ else
+ {
+ if (m_dock_cart_type == TIMEX_CART_DOCK)
+ {
+ membank("bank8")->set_base(DOCK+0xe000);
+ space.install_read_bank(0xe000, 0xffff, "bank8");
+ if (m_ram_chunks & 0x80)
+ space.install_write_bank(0xe000, 0xffff, "bank16");
+ else
+ space.unmap_write(0xe000, 0xffff);
+ }
+ else
+ {
+ space.nop_read(0xe000, 0xffff);
+ space.unmap_write(0xe000, 0xffff);
+ }
+ logerror("e000-ffff Cartridge\n");
+ }
+ }
+ else
+ {
+ membank("bank8")->set_base(messram + 0xa000);
+ membank("bank16")->set_base(messram + 0xa000);
+ space.install_read_bank(0xe000, 0xffff, "bank8");
+ space.install_write_bank(0xe000, 0xffff, "bank16");
+ logerror("e000-ffff RAM\n");
+ }
+}
+
+static ADDRESS_MAP_START(ts2068_io, AS_IO, 8, spectrum_state )
+ AM_RANGE(0x1f, 0x1f) AM_READ(spectrum_port_1f_r ) AM_MIRROR(0xff00)
+ AM_RANGE(0x7f, 0x7f) AM_READ(spectrum_port_7f_r ) AM_MIRROR(0xff00)
+ AM_RANGE(0xdf, 0xdf) AM_READ(spectrum_port_df_r ) AM_MIRROR(0xff00)
+ AM_RANGE(0xf4, 0xf4) AM_READWRITE(ts2068_port_f4_r,ts2068_port_f4_w ) AM_MIRROR(0xff00)
+ AM_RANGE(0xf5, 0xf5) AM_DEVWRITE("ay8912", ay8910_device, address_w ) AM_MIRROR(0xff00)
+ AM_RANGE(0xf6, 0xf6) AM_DEVREADWRITE("ay8912", ay8910_device, data_r, data_w ) AM_MIRROR(0xff00)
+ AM_RANGE(0xfe, 0xfe) AM_READWRITE(spectrum_port_fe_r,spectrum_port_fe_w ) AM_MIRROR(0xff00) AM_MASK(0xffff)
+ AM_RANGE(0xff, 0xff) AM_READWRITE(ts2068_port_ff_r,ts2068_port_ff_w ) AM_MIRROR(0xff00)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(ts2068_mem, AS_PROGRAM, 8, spectrum_state )
+ AM_RANGE(0x0000, 0x1fff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank9")
+ AM_RANGE(0x2000, 0x3fff) AM_READ_BANK("bank2") AM_WRITE_BANK("bank10")
+ AM_RANGE(0x4000, 0x5fff) AM_READ_BANK("bank3") AM_WRITE_BANK("bank11")
+ AM_RANGE(0x6000, 0x7fff) AM_READ_BANK("bank4") AM_WRITE_BANK("bank12")
+ AM_RANGE(0x8000, 0x9fff) AM_READ_BANK("bank5") AM_WRITE_BANK("bank13")
+ AM_RANGE(0xa000, 0xbfff) AM_READ_BANK("bank6") AM_WRITE_BANK("bank14")
+ AM_RANGE(0xc000, 0xdfff) AM_READ_BANK("bank7") AM_WRITE_BANK("bank15")
+ AM_RANGE(0xe000, 0xffff) AM_READ_BANK("bank8") AM_WRITE_BANK("bank16")
+ADDRESS_MAP_END
+
+
+MACHINE_RESET_MEMBER(spectrum_state,ts2068)
+{
+ m_port_ff_data = 0;
+ m_port_f4_data = 0;
+
+ std::string region_tag;
+ m_dock_crt = memregion(region_tag.assign(m_dock->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
+ m_dock_cart_type = m_dock_crt ? TIMEX_CART_DOCK : TIMEX_CART_NONE;
+
+ ts2068_update_memory();
+ MACHINE_RESET_CALL_MEMBER(spectrum);
+}
+
+
+/****************************************************************************************************/
+/* TC2048 specific functions */
+
+
+WRITE8_MEMBER( spectrum_state::tc2048_port_ff_w )
+{
+ m_port_ff_data = data;
+ logerror("Port %04x write %02x\n", offset, data);
+}
+
+static ADDRESS_MAP_START(tc2048_io, AS_IO, 8, spectrum_state )
+ AM_RANGE(0x00, 0x00) AM_READWRITE(spectrum_port_fe_r,spectrum_port_fe_w) AM_MIRROR(0xfffe) AM_MASK(0xffff)
+ AM_RANGE(0x1f, 0x1f) AM_READ(spectrum_port_1f_r) AM_MIRROR(0xff00)
+ AM_RANGE(0x7f, 0x7f) AM_READ(spectrum_port_7f_r) AM_MIRROR(0xff00)
+ AM_RANGE(0xdf, 0xdf) AM_READ(spectrum_port_df_r) AM_MIRROR(0xff00)
+ AM_RANGE(0xff, 0xff) AM_READWRITE(ts2068_port_ff_r,tc2048_port_ff_w) AM_MIRROR(0xff00)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(tc2048_mem, AS_PROGRAM, 8, spectrum_state )
+ AM_RANGE( 0x0000, 0x3fff) AM_ROM
+ AM_RANGE( 0x4000, 0xffff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank2")
+ADDRESS_MAP_END
+
+MACHINE_RESET_MEMBER(spectrum_state,tc2048)
+{
+ UINT8 *messram = m_ram->pointer();
+
+ membank("bank1")->set_base(messram);
+ membank("bank2")->set_base(messram);
+ m_port_ff_data = 0;
+ m_port_f4_data = -1;
+ MACHINE_RESET_CALL_MEMBER(spectrum);
+}
+
+
+DEVICE_IMAGE_LOAD_MEMBER( spectrum_state, timex_cart )
+{
+ UINT32 size = m_dock->common_get_size("rom");
+
+ if (image.software_entry() == NULL)
+ {
+ UINT8 *DOCK;
+ int chunks_in_file = 0;
+ dynamic_buffer header;
+ header.resize(9);
+
+ if (size % 0x2000 != 9)
+ {
+ image.seterror(IMAGE_ERROR_UNSPECIFIED, "File corrupted");
+ return IMAGE_INIT_FAIL;
+ }
+ if (image.software_entry() != NULL)
+ {
+ image.seterror(IMAGE_ERROR_UNSPECIFIED, "Loading from softlist is not supported yet");
+ return IMAGE_INIT_FAIL;
+ }
+
+ m_dock->rom_alloc(0x10000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
+ DOCK = m_dock->get_rom_base();
+
+ // check header
+ image.fread(&header[0], 9);
+
+ for (int i = 0; i < 8; i++)
+ if (header[i + 1] & 0x02) chunks_in_file++;
+
+ if (chunks_in_file * 0x2000 + 0x09 != size)
+ {
+ image.seterror(IMAGE_ERROR_UNSPECIFIED, "File corrupted");
+ return IMAGE_INIT_FAIL;
+ }
+
+ switch (header[0])
+ {
+ case 0x00: logerror ("DOCK cart\n");
+ m_ram_chunks = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ m_ram_chunks = m_ram_chunks | ((header[i + 1] & 0x01) << i);
+ if (header[i + 1] & 0x02)
+ image.fread(DOCK + i * 0x2000, 0x2000);
+ else
+ {
+ if (header[i + 1] & 0x01)
+ memset(DOCK + i * 0x2000, 0x00, 0x2000);
+ else
+ memset(DOCK + i * 0x2000, 0xff, 0x2000);
+ }
+ }
+ break;
+
+ default:
+ image.seterror(IMAGE_ERROR_UNSPECIFIED, "Cart type not supported");
+ return IMAGE_INIT_FAIL;
+ }
+
+ logerror ("Cart loaded [Chunks %02x]\n", m_ram_chunks);
+ }
+ else
+ {
+ m_dock->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
+ memcpy(m_dock->get_rom_base(), image.get_software_region("rom"), size);
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+/* F4 Character Displayer - tc2048 code is inherited from the spectrum */
+static const gfx_layout ts2068_charlayout =
+{
+ 8, 8, /* 8 x 8 characters */
+ 96, /* 96 characters */
+ 1, /* 1 bits per pixel */
+ { 0 }, /* no bitplanes */
+ /* x offsets */
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ /* y offsets */
+ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
+ 8*8 /* every char takes 8 bytes */
+};
+
+static GFXDECODE_START( ts2068 )
+ GFXDECODE_ENTRY( "maincpu", 0x13d00, ts2068_charlayout, 0, 8 )
+GFXDECODE_END
+
+static MACHINE_CONFIG_DERIVED( ts2068, spectrum_128 )
+ MCFG_CPU_REPLACE("maincpu", Z80, XTAL_14_112MHz/4) /* From Schematic; 3.528 MHz */
+ MCFG_CPU_PROGRAM_MAP(ts2068_mem)
+ MCFG_CPU_IO_MAP(ts2068_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", spectrum_state, spec_interrupt)
+ MCFG_QUANTUM_TIME(attotime::from_hz(60))
+
+ MCFG_MACHINE_RESET_OVERRIDE(spectrum_state, ts2068 )
+
+ /* video hardware */
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_SIZE(TS2068_SCREEN_WIDTH, TS2068_SCREEN_HEIGHT)
+ MCFG_SCREEN_VISIBLE_AREA(0, TS2068_SCREEN_WIDTH-1, 0, TS2068_SCREEN_HEIGHT-1)
+ MCFG_SCREEN_UPDATE_DRIVER(spectrum_state, screen_update_ts2068)
+ MCFG_SCREEN_VBLANK_DRIVER(spectrum_state, screen_eof_timex)
+
+ MCFG_GFXDECODE_MODIFY("gfxdecode", ts2068)
+
+ MCFG_VIDEO_START_OVERRIDE(spectrum_state, ts2068 )
+
+ /* sound */
+ MCFG_SOUND_REPLACE("ay8912", AY8912, XTAL_14_112MHz/8) /* From Schematic; 1.764 MHz */
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ /* cartridge */
+ MCFG_DEVICE_REMOVE("cartslot")
+ MCFG_GENERIC_CARTSLOT_ADD("dockslot", generic_plain_slot, "timex_cart")
+ MCFG_GENERIC_EXTENSIONS("dck,bin")
+ MCFG_GENERIC_LOAD(spectrum_state, timex_cart)
+
+ /* Software lists */
+ MCFG_DEVICE_REMOVE("cart_list")
+ MCFG_SOFTWARE_LIST_ADD("cart_list", "timex_dock")
+
+ /* internal ram */
+ MCFG_RAM_MODIFY(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("48K")
+MACHINE_CONFIG_END
+
+
+static MACHINE_CONFIG_DERIVED( uk2086, ts2068 )
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_REFRESH_RATE(50)
+MACHINE_CONFIG_END
+
+
+static MACHINE_CONFIG_DERIVED( tc2048, spectrum )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(tc2048_mem)
+ MCFG_CPU_IO_MAP(tc2048_io)
+
+ MCFG_MACHINE_RESET_OVERRIDE(spectrum_state, tc2048 )
+
+ /* video hardware */
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_REFRESH_RATE(50)
+ MCFG_SCREEN_SIZE(TS2068_SCREEN_WIDTH, SPEC_SCREEN_HEIGHT)
+ MCFG_SCREEN_VISIBLE_AREA(0, TS2068_SCREEN_WIDTH-1, 0, SPEC_SCREEN_HEIGHT-1)
+ MCFG_SCREEN_UPDATE_DRIVER(spectrum_state, screen_update_tc2048)
+ MCFG_SCREEN_VBLANK_DRIVER(spectrum_state, screen_eof_timex)
+
+ MCFG_VIDEO_START_OVERRIDE(spectrum_state, spectrum_128 )
+
+ /* internal ram */
+ MCFG_RAM_MODIFY(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("48K")
+MACHINE_CONFIG_END
+
+
+
+/***************************************************************************
+
+ Game driver(s)
+
+***************************************************************************/
+
+ROM_START(tc2048)
+ ROM_REGION(0x10000,"maincpu",0)
+ ROM_LOAD("tc2048.rom",0x0000,0x4000, CRC(f1b5fa67) SHA1(febb2d495b6eda7cdcb4074935d6e9d9f328972d))
+ROM_END
+
+ROM_START(ts2068)
+ ROM_REGION(0x16000,"maincpu",0)
+ ROM_LOAD("ts2068_h.rom",0x10000,0x4000, CRC(bf44ec3f) SHA1(1446cb2780a9dedf640404a639fa3ae518b2d8aa))
+ ROM_LOAD("ts2068_x.rom",0x14000,0x2000, CRC(ae16233a) SHA1(7e265a2c1f621ed365ea23bdcafdedbc79c1299c))
+ROM_END
+
+ROM_START(uk2086)
+ ROM_REGION(0x16000,"maincpu",0)
+ ROM_LOAD("uk2086_h.rom",0x10000,0x4000, CRC(5ddc0ca2) SHA1(1d525fe5cdc82ab46767f665ad735eb5363f1f51))
+ ROM_LOAD("ts2068_x.rom",0x14000,0x2000, CRC(ae16233a) SHA1(7e265a2c1f621ed365ea23bdcafdedbc79c1299c))
+ROM_END
+
+/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
+COMP( 1984, tc2048, spectrum, 0, tc2048, spectrum, driver_device, 0, "Timex of Portugal", "TC-2048" , 0)
+COMP( 1983, ts2068, spectrum, 0, ts2068, spectrum, driver_device, 0, "Timex Sinclair", "TS-2068" , 0)
+COMP( 1986, uk2086, spectrum, 0, uk2086, spectrum, driver_device, 0, "Unipolbrit", "UK-2086 ver. 1.2" , 0)