summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/mtx.cpp
blob: 5c081036b0ae15f92ee64dbe868b03b9d6af769b (plain) (tree)
1
2
3
4
                       
                                                    

                                                                          










                                                                           
                                    












                                                                            
                                     
 
                            
                                          




                                                   
























                                                                                                              



















                                                                     
                                        


          











                               
                                                              
 


                                              
 
                     
         





































                                                                                     


            



















                                                                                                                     




                                          
                         





                                                   
                                           
 
                                             








                                                   






                                                   
                                   
 
                                                   


                                                   








                                                                                                               


                                                   















                                                     
 

                                    
 

                                  

          
                               
 







                         
 
          
 
                         

                                  
                                          
 



                                         









                                                   








                                                   
                            


















                                                                  
                                                      






















                                                                       
                                       
 







                                                         
 
                  




                  
                                       
 







                              
 
                  




































                                                   
                               
 







             
 
          


                                                                            







































                                                                                      


                                                                            

                                                                     
                                      
 
                                                              
                  
                           
 

                                             
 

                              
         
                                                                  
                                               
         







                                                 
                                                                        

                                 
                                           

                                       
         


                                                                       

         
                                  
                                                                        












                                                                                                                                  
                                       









                                                                            
                                       
 
                                                              
 


























                                                                                              

 
                                       

                            
                      
 
// license:BSD-3-Clause
// copyright-holders:Lee Ward, Dirk Best, Curt Coder
/*************************************************************************

    Memotech MTX 500, MTX 512 and RS 128

**************************************************************************/

#include "emu.h"
#include "formats/imageutl.h"
#include "includes/mtx.h"
#include "cpu/z80/z80.h"
#include "imagedev/cassette.h"
#include "machine/ram.h"
#include "imagedev/snapquik.h"
#include "bus/centronics/ctronics.h"
#include "machine/z80ctc.h"
#include "machine/z80dart.h"
#include "video/tms9928a.h"
#include "sound/sn76496.h"

/***************************************************************************
    READ/WRITE HANDLERS
***************************************************************************/

/*-------------------------------------------------
    mtx_strobe_r - centronics strobe
-------------------------------------------------*/

READ8_MEMBER(mtx_state::mtx_strobe_r)
{
	/* set STROBE low */
	m_centronics->write_strobe(false);

	return 0xff;
}

/*-------------------------------------------------
    mtx_subpage_w - rom2 subpages
-------------------------------------------------*/

/*
    The original ROM card supported 4 8KB ROM chips. These appeared in
    ROM slot 2 in subpages 0 to 3. The subpage register starts as 0, but
    is changed by attempting to write to 0x0000-0x1fff whilst in RELCPMH=0
    mode (ie. attempting to write to the OS ROM). Videowalls could use a
    later ROM card with 4 32KB ROMs. These also appeared in ROM slot 2
    in subpages 0 to 15.
*/

WRITE8_MEMBER(mtx_state::mtx_subpage_w)
{
	if (m_extrom->exists())
	{
		if ((data * 0x2000) < m_extrom->get_rom_size())
			membank("rommap_bank1")->configure_entry(2, m_extrom->get_rom_base() + 0x2000 * data);
		else
			membank("rommap_bank1")->configure_entry(2, memregion("user2")->base() + 0x4000);
		membank("rommap_bank1")->set_entry(2);
	}
}

/*-------------------------------------------------
    mtx_bankswitch_w - bankswitch
-------------------------------------------------*/

/*
    There are two memory models on the MTX, the standard one and a
    CBM mode. In standard mode, the memory map is defined as:

    0x0000 - 0x1fff  OSROM
    0x2000 - 0x3fff  Paged ROM
    0x4000 - 0x7fff  Paged RAM
    0x8000 - 0xbfff  Paged RAM
    0xc000 - 0xffff  RAM

    Banks are selected by output port 0. Bits 0-3 define the RAM page
    and bits 4-6 the ROM page.

    CBM mode is selected by bit 7 of output port 0. ROM is replaced
    by RAM in this mode.
*/

void mtx_state::bankswitch(uint8_t data)
{
	/*

	    bit     description

	    0       P0
	    1       P1
	    2       P2
	    3       P3
	    4       R0
	    5       R1
	    6       R2
	    7       RELCPMH

	*/
	address_space &program = m_maincpu->space(AS_PROGRAM);

	uint8_t cbm_mode = (data >> 7) & 0x01;
	uint8_t rom_page = (data >> 4) & 0x07;
	uint8_t ram_page = (data >> 0) & 0x0f;

	if (cbm_mode)
	{
		/* ram based memory map */
		program.install_readwrite_bank(0x0000, 0x3fff, "rammap_bank1");
		program.install_readwrite_bank(0x4000, 0x7fff, "rammap_bank2");
		program.install_readwrite_bank(0x8000, 0xbfff, "rammap_bank3");

		/* set ram bank, for invalid pages a nop-handler will be installed */
		switch (ram_page)
		{
		case 0:
			if (ram_page * 0xc000 + 0x10000 <= m_ram->size())
				membank("rammap_bank1")->set_entry(ram_page);
			else
				program.nop_readwrite(0x0000, 0x3fff);
			if (ram_page * 0xc000 + 0xc000 <= m_ram->size())
				membank("rammap_bank2")->set_entry(ram_page);
			else
				program.nop_readwrite(0x4000, 0x7fff);
			if (ram_page * 0xc000 + 0x8000 <= m_ram->size())
				membank("rammap_bank3")->set_entry(ram_page);
			else
				program.nop_readwrite(0x8000, 0xbfff);
			break;

		default:
			if (ram_page * 0xc000 + 0x8000 <= m_ram->size())
				membank("rammap_bank1")->set_entry(ram_page);
			else
				program.nop_readwrite(0x0000, 0x3fff);
			if (ram_page * 0xc000 + 0xc000 <= m_ram->size())
				membank("rammap_bank2")->set_entry(ram_page);
			else
				program.nop_readwrite(0x4000, 0x7fff);
			if (ram_page * 0xc000 + 0x10000 <= m_ram->size())
				membank("rammap_bank3")->set_entry(ram_page);
			else
				program.nop_readwrite(0x8000, 0xbfff);
			break;
		}
	}
	else
	{
		/* rom based memory map */
		program.install_rom(0x0000, 0x1fff, memregion("user1")->base());
		program.install_write_handler(0x0000, 0x1fff, write8_delegate(FUNC(mtx_state::mtx_subpage_w), this));
		program.install_read_bank(0x2000, 0x3fff, "rommap_bank1");
		program.unmap_write(0x2000, 0x3fff);
		program.install_readwrite_bank(0x4000, 0x7fff, "rommap_bank2");
		program.install_readwrite_bank(0x8000, 0xbfff, "rommap_bank3");

		/* set rom bank (switches between basic and assembler rom or cartridges) */
		membank("rommap_bank1")->set_entry(rom_page);

		/* set ram bank, for invalid pages a nop-handler will be installed */
		if (ram_page * 0x8000 + 0xc000 <= m_ram->size())
			membank("rommap_bank2")->set_entry(ram_page);
		else
			program.nop_readwrite(0x4000, 0x7fff);
		if (ram_page * 0x8000 + 0x8000 <= m_ram->size())
			membank("rommap_bank3")->set_entry(ram_page);
		else
			program.nop_readwrite(0x8000, 0xbfff);
	}
}

WRITE8_MEMBER(mtx_state::mtx_bankswitch_w)
{
	bankswitch(data);
}

/*-------------------------------------------------
    mtx_sound_strobe_r - sound strobe
-------------------------------------------------*/

READ8_MEMBER(mtx_state::mtx_sound_strobe_r)
{
	m_sn->write(space, 0, m_sound_latch);
	return 0xff;
}

/*-------------------------------------------------
    mtx_sound_latch_w - sound latch write
-------------------------------------------------*/

WRITE8_MEMBER(mtx_state::mtx_sound_latch_w)
{
	m_sound_latch = data;
}

/*-------------------------------------------------
    mtx_cst_w - cassette write
-------------------------------------------------*/

WRITE8_MEMBER(mtx_state::mtx_cst_w)
{
	m_cassette->output( BIT(data, 0) ? -1 : 1);
}

/*-------------------------------------------------
    mtx_cst_motor_w - cassette motor
-------------------------------------------------*/

WRITE8_MEMBER(mtx_state::mtx_cst_motor_w)
{
	m_cassette->change_state(data ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
}

/*-------------------------------------------------
    mtx_prt_r - centronics status
-------------------------------------------------*/

WRITE_LINE_MEMBER(mtx_state::write_centronics_busy)
{
	m_centronics_busy = state;
}

WRITE_LINE_MEMBER(mtx_state::write_centronics_fault)
{
	m_centronics_fault = state;
}

WRITE_LINE_MEMBER(mtx_state::write_centronics_perror)
{
	m_centronics_perror = state;
}

WRITE_LINE_MEMBER(mtx_state::write_centronics_select)
{
	m_centronics_select = state;
}

READ8_MEMBER(mtx_state::mtx_prt_r)
{
	/*

	    bit     description

	    0       BUSY
	    1       ERROR
	    2       PE
	    3       SLCT
	    4
	    5
	    6
	    7

	*/

	uint8_t data = 0;

	/* reset STROBE to high */
	m_centronics->write_strobe( true);

	data |= m_centronics_busy << 0;
	data |= m_centronics_fault << 1;
	data |= m_centronics_perror << 2;
	data |= m_centronics_select << 3;

	return data;
}

/*-------------------------------------------------
    mtx_sense_w - keyboard sense write
-------------------------------------------------*/

WRITE8_MEMBER(mtx_state::mtx_sense_w)
{
	m_key_sense = data;
}

/*-------------------------------------------------
    mtx_key_lo_r - keyboard low read
-------------------------------------------------*/

READ8_MEMBER(mtx_state::mtx_key_lo_r)
{
	uint8_t data = 0xff;

	if (!(m_key_sense & 0x01)) data &= ioport("ROW0")->read();
	if (!(m_key_sense & 0x02)) data &= ioport("ROW1")->read();
	if (!(m_key_sense & 0x04)) data &= ioport("ROW2")->read();
	if (!(m_key_sense & 0x08)) data &= ioport("ROW3")->read();
	if (!(m_key_sense & 0x10)) data &= ioport("ROW4")->read();
	if (!(m_key_sense & 0x20)) data &= ioport("ROW5")->read();
	if (!(m_key_sense & 0x40)) data &= ioport("ROW6")->read();
	if (!(m_key_sense & 0x80)) data &= ioport("ROW7")->read();

	return data;
}

/*-------------------------------------------------
    mtx_key_lo_r - keyboard high read
-------------------------------------------------*/

READ8_MEMBER(mtx_state::mtx_key_hi_r)
{
	uint8_t data = ioport("country_code")->read();

	if (!(m_key_sense & 0x01)) data &= ioport("ROW0")->read() >> 8;
	if (!(m_key_sense & 0x02)) data &= ioport("ROW1")->read() >> 8;
	if (!(m_key_sense & 0x04)) data &= ioport("ROW2")->read() >> 8;
	if (!(m_key_sense & 0x08)) data &= ioport("ROW3")->read() >> 8;
	if (!(m_key_sense & 0x10)) data &= ioport("ROW4")->read() >> 8;
	if (!(m_key_sense & 0x20)) data &= ioport("ROW5")->read() >> 8;
	if (!(m_key_sense & 0x40)) data &= ioport("ROW6")->read() >> 8;
	if (!(m_key_sense & 0x80)) data &= ioport("ROW7")->read() >> 8;

	return data;
}

/*-------------------------------------------------
    hrx_address_w - HRX video RAM address
-------------------------------------------------*/

WRITE8_MEMBER(mtx_state::hrx_address_w)
{
	if (offset)
	{
		/*

		    bit     description

		    0       A8
		    1       A9
		    2       A10
		    3
		    4
		    5       attribute memory write enable
		    6       ASCII memory write enable
		    7       cycle (0=read/1=write)

		*/
	}
	else
	{
		/*

		    bit     description

		    0       A0
		    1       A1
		    2       A2
		    3       A3
		    4       A4
		    5       A5
		    6       A6
		    7       A7

		*/
	}
}

/*-------------------------------------------------
    hrx_data_r - HRX data read
-------------------------------------------------*/

READ8_MEMBER(mtx_state::hrx_data_r)
{
	return 0;
}

/*-------------------------------------------------
    hrx_data_w - HRX data write
-------------------------------------------------*/

WRITE8_MEMBER(mtx_state::hrx_data_w)
{
}

/*-------------------------------------------------
    hrx_attr_r - HRX attribute read
-------------------------------------------------*/

READ8_MEMBER(mtx_state::hrx_attr_r)
{
	return 0;
}

/*-------------------------------------------------
    hrx_attr_r - HRX attribute write
-------------------------------------------------*/

WRITE8_MEMBER(mtx_state::hrx_attr_w)
{
	/*

	    bit     description

	    0
	    1
	    2
	    3
	    4
	    5
	    6
	    7

	*/
}

/***************************************************************************
    EXTENSION BOARD ROMS
***************************************************************************/

DEVICE_IMAGE_LOAD_MEMBER( mtx_state, extrom_load )
{
	uint32_t size = m_extrom->common_get_size("rom");

	if (size > 0x80000)
	{
		image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported rom size");
		return image_init_result::FAIL;
	}

	m_extrom->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
	m_extrom->common_load_rom(m_extrom->get_rom_base(), size, "rom");

	return image_init_result::PASS;
}

/***************************************************************************
    ROMPAK ROMS
***************************************************************************/

DEVICE_IMAGE_LOAD_MEMBER( mtx_state, rompak_load )
{
	uint32_t size = m_rompak->common_get_size("rom");

	if (size > 0x2000)
	{
		image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
		return image_init_result::FAIL;
	}

	m_rompak->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
	m_rompak->common_load_rom(m_rompak->get_rom_base(), size, "rom");

	return image_init_result::PASS;
}

/***************************************************************************
    SNAPSHOT
***************************************************************************/

// this only works for some of the files, nothing which tries to load
// more data from tape. todo: tapes which autorun after loading
SNAPSHOT_LOAD_MEMBER( mtx_state, mtx )
{
	address_space &program = m_maincpu->space(AS_PROGRAM);
	void *ptr;
	uint8_t header[18];

	// read header
	image.fread(&header, sizeof(header));

	// verify first byte
	if (header[0] != 0xff)
	{
		image.seterror(IMAGE_ERROR_INVALIDIMAGE, nullptr);
		return image_init_result::FAIL;
	}

	// get tape name
	char tape_name[16];
	memcpy(&tape_name, &header[1], 15);
	tape_name[15] = '\0';
	image.message("Loading '%s'", tape_name);

	// start of system variables area
	uint16_t system_variables_base = pick_integer_le(header, 16, 2);

	// write system variables
	uint16_t system_variables_size = 0;

	if (system_variables_base != 0)
	{
		ptr = program.get_write_ptr(system_variables_base);
		system_variables_size = 0xfb4b - system_variables_base;
		image.fread(ptr, system_variables_size);
	}

	// write actual image data
	uint16_t data_size = snapshot_size - 18 - system_variables_size;

	ptr = program.get_write_ptr(0x4000);
	image.fread(ptr, 0x4000);

	// if we cross the page boundary, get a new write pointer and write the rest
	if (data_size > 0x4000)
	{
		ptr = program.get_write_ptr(0x8000);
		image.fread(ptr, 0x4000);
	}

	logerror("snapshot name = '%s', system_size = 0x%04x, data_size = 0x%04x\n", tape_name, system_variables_size, data_size);

	return image_init_result::PASS;
}

/***************************************************************************
    MACHINE INITIALIZATION
***************************************************************************/

/*-------------------------------------------------
    MACHINE_START( mtx512 )
-------------------------------------------------*/

MACHINE_START_MEMBER(mtx_state, mtx512)
{
	address_space &program = m_maincpu->space(AS_PROGRAM);

	/* setup banks for rom based memory map */
	program.install_read_bank(0x2000, 0x3fff, "rommap_bank1");
	program.install_readwrite_bank(0x4000, 0x7fff, "rommap_bank2");
	program.install_readwrite_bank(0x8000, 0xbfff, "rommap_bank3");

	membank("rommap_bank1")->configure_entries(0, 8, memregion("user2")->base(), 0x2000);
	if (m_extrom->exists())
		membank("rommap_bank1")->configure_entry(2, m_extrom->get_rom_base());
	if (m_rompak->exists())
		membank("rommap_bank1")->configure_entry(7, m_rompak->get_rom_base());
	membank("rommap_bank2")->configure_entries(0, 16, m_ram->pointer() + 0x8000, 0x8000);
	membank("rommap_bank3")->configure_entries(0, 16, m_ram->pointer() + 0x4000, 0x8000);

	/* setup banks for ram based memory map */
	program.install_readwrite_bank(0x0000, 0x3fff, "rammap_bank1");
	program.install_readwrite_bank(0x4000, 0x7fff, "rammap_bank2");
	program.install_readwrite_bank(0x8000, 0xbfff, "rammap_bank3");

	membank("rammap_bank1")->configure_entry(0, m_ram->pointer() + 0xc000);
	membank("rammap_bank1")->configure_entries(1, 15, m_ram->pointer() + 0x10000, 0xc000);
	membank("rammap_bank2")->configure_entry(0, m_ram->pointer() + 0x8000);
	membank("rammap_bank2")->configure_entries(1, 15, m_ram->pointer() + 0x14000, 0xc000);
	membank("rammap_bank3")->configure_entry(0, m_ram->pointer() + 0x4000);
	membank("rammap_bank3")->configure_entries(1, 15, m_ram->pointer() + 0x18000, 0xc000);

	/* install 4000h bytes common block */
	program.install_ram(0xc000, 0xffff, m_ram->pointer());
}

MACHINE_RESET_MEMBER(mtx_state, mtx512)
{
	/* bank switching */
	bankswitch(0);
}