mirror of
https://github.com/holub/mame
synced 2025-05-17 19:24:59 +03:00
825 lines
25 KiB
C
825 lines
25 KiB
C
/***************************************************************************
|
|
|
|
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/cartslot.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"
|
|
|
|
enum
|
|
{
|
|
TIMEX_CART_NONE,
|
|
TIMEX_CART_DOCK,
|
|
TIMEX_CART_EXROM,
|
|
TIMEX_CART_HOME
|
|
};
|
|
|
|
struct timex_cart_t
|
|
{
|
|
int type;
|
|
UINT8 chunks;
|
|
UINT8 *data;
|
|
};
|
|
|
|
static timex_cart_t timex_cart;
|
|
|
|
const timex_cart_t *timex_cart_data(void)
|
|
{
|
|
return &timex_cart;
|
|
}
|
|
|
|
static const ay8910_interface spectrum_ay_interface =
|
|
{
|
|
AY8910_LEGACY_OUTPUT,
|
|
AY8910_DEFAULT_LOADS,
|
|
DEVCB_NULL
|
|
};
|
|
|
|
/****************************************************************************************************/
|
|
/* 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);
|
|
unsigned char *ChosenROM, *ExROM;
|
|
const timex_cart_t *timex_cart = timex_cart_data();
|
|
int timex_cart_type = timex_cart->type;
|
|
UINT8 timex_cart_chunks = timex_cart->chunks;
|
|
UINT8 *DOCK = timex_cart->data;
|
|
|
|
ExROM = memregion("maincpu")->base() + 0x014000;
|
|
|
|
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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank1")->set_base(DOCK);
|
|
space.install_read_bank(0x0000, 0x1fff, "bank1");
|
|
if (timex_cart_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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank2")->set_base(DOCK+0x2000);
|
|
space.install_read_bank(0x2000, 0x3fff, "bank2");
|
|
if (timex_cart_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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank3")->set_base(DOCK+0x4000);
|
|
space.install_read_bank(0x4000, 0x5fff, "bank3");
|
|
if (timex_cart_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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank4")->set_base(DOCK+0x6000);
|
|
space.install_read_bank(0x6000, 0x7fff, "bank4");
|
|
if (timex_cart_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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank5")->set_base(DOCK+0x8000);
|
|
space.install_read_bank(0x8000, 0x9fff,"bank5");
|
|
if (timex_cart_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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank6")->set_base(DOCK+0xa000);
|
|
space.install_read_bank(0xa000, 0xbfff, "bank6");
|
|
if (timex_cart_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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank7")->set_base(DOCK+0xc000);
|
|
space.install_read_bank(0xc000, 0xdfff, "bank7");
|
|
if (timex_cart_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 (timex_cart_type == TIMEX_CART_DOCK)
|
|
{
|
|
membank("bank8")->set_base(DOCK+0xe000);
|
|
space.install_read_bank(0xe000, 0xffff, "bank8");
|
|
if (timex_cart_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_LEGACY("ay8912", ay8910_address_w ) AM_MIRROR(0xff00)
|
|
AM_RANGE(0xf6, 0xf6) AM_DEVREADWRITE_LEGACY("ay8912", ay8910_r, ay8910_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;
|
|
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 )
|
|
{
|
|
int file_size;
|
|
UINT8 * file_data;
|
|
|
|
int chunks_in_file = 0;
|
|
|
|
int i;
|
|
|
|
logerror ("Trying to load cart\n");
|
|
|
|
file_size = image.length();
|
|
|
|
if (file_size < 0x09)
|
|
{
|
|
logerror ("Bad file size\n");
|
|
return IMAGE_INIT_FAIL;
|
|
}
|
|
|
|
file_data = (UINT8 *)malloc(file_size);
|
|
if (file_data == NULL)
|
|
{
|
|
logerror ("Memory allocating error\n");
|
|
return IMAGE_INIT_FAIL;
|
|
}
|
|
|
|
image.fread(file_data, file_size);
|
|
|
|
for (i=0; i<8; i++)
|
|
if(file_data[i+1]&0x02) chunks_in_file++;
|
|
|
|
if (chunks_in_file*0x2000+0x09 != file_size)
|
|
{
|
|
free (file_data);
|
|
logerror ("File corrupted\n");
|
|
return IMAGE_INIT_FAIL;
|
|
}
|
|
|
|
switch (file_data[0x00])
|
|
{
|
|
case 0x00: logerror ("DOCK cart\n");
|
|
timex_cart.type = TIMEX_CART_DOCK;
|
|
timex_cart.data = (UINT8*) malloc (0x10000);
|
|
if (!timex_cart.data)
|
|
{
|
|
free (file_data);
|
|
logerror ("Memory allocate error\n");
|
|
return IMAGE_INIT_FAIL;
|
|
}
|
|
chunks_in_file = 0;
|
|
for (i=0; i<8; i++)
|
|
{
|
|
timex_cart.chunks = timex_cart.chunks | ((file_data[i+1]&0x01)<<i);
|
|
if (file_data[i+1]&0x02)
|
|
{
|
|
memcpy (timex_cart.data+i*0x2000, file_data+0x09+chunks_in_file*0x2000, 0x2000);
|
|
chunks_in_file++;
|
|
}
|
|
else
|
|
{
|
|
if (file_data[i+1]&0x01)
|
|
memset (timex_cart.data+i*0x2000, 0x00, 0x2000);
|
|
else
|
|
memset (timex_cart.data+i*0x2000, 0xff, 0x2000);
|
|
}
|
|
}
|
|
free (file_data);
|
|
break;
|
|
|
|
default: logerror ("Cart type not supported\n");
|
|
free (file_data);
|
|
timex_cart.type = TIMEX_CART_NONE;
|
|
return IMAGE_INIT_FAIL;
|
|
}
|
|
|
|
logerror ("Cart loaded\n");
|
|
logerror ("Chunks %02x\n", timex_cart.chunks);
|
|
return IMAGE_INIT_PASS;
|
|
}
|
|
|
|
|
|
DEVICE_IMAGE_UNLOAD_MEMBER( spectrum_state, timex_cart )
|
|
{
|
|
if (timex_cart.data)
|
|
{
|
|
free (timex_cart.data);
|
|
timex_cart.data = NULL;
|
|
}
|
|
timex_cart.type = TIMEX_CART_NONE;
|
|
timex_cart.chunks = 0x00;
|
|
}
|
|
|
|
|
|
/* 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_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_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_CONFIG(spectrum_ay_interface)
|
|
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
|
|
|
|
/* cartridge */
|
|
MCFG_CARTSLOT_MODIFY("cart")
|
|
MCFG_CARTSLOT_EXTENSION_LIST("dck")
|
|
MCFG_CARTSLOT_NOT_MANDATORY
|
|
MCFG_CARTSLOT_LOAD(spectrum_state,timex_cart)
|
|
MCFG_CARTSLOT_UNLOAD(spectrum_state,timex_cart)
|
|
|
|
/* 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_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_CART_LOAD("cart", 0x0000, 0x4000, ROM_NOCLEAR | ROM_NOMIRROR | ROM_OPTIONAL)
|
|
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)
|