summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/super80.cpp
blob: 6296d2920273d2130263fa3c5d95adfab898aa90 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11

                             
                                                                                      
 
                
                             
                           



                                                                                                                 
                                         

                          
                                                               
 
 
                                     
 
                            
 
                                   

                                                         
 

                          
                    
 
 

                                                                                                                  
                                                      
 




                                                         
                                                                                      
            
                                                                                     

                                               
                                        
                                                                                         
            
                                                                                       




                                                                                                      






                                                                                          
                                                    
 
 
                        

                                                                                                       
 

                                                                                                 
 


                                        
                                                       
 
                          
 
                         
                                                          
 
                                      
         
                                                                           
                                         
                                                                                              
                                   
         

 
 
                                                      
 
                            
                                                                                                                                  
                                                                          



                                                                                      
                              
                                                                                                        
 

                                 
                 
                                                                                                           
                                     



                 
                                                                                         
                 
                                                                               
                                                                                    
















                                                                                                           
                             
 
                                                                          

 
                                                
                                      
 
                                                                    
                                   
 
                                              

                                                           

                                                           





                                  
                                           


                                    

 
                            
 
                                                                  

                                                                                                                   


                    
                                     
 
                                                                   
                                     

                                      


 
                                     
 
                                     
                        


                                                                                  



                           


                                                                                                                     
                                          
 
                             
 
                                  















                                            



                                    


                                                 



                                          
 
                                  
                                                                                         

                          
                            
















                                                                                                                               

 
                                   
 
                               
                         

 
                                    
 
                               

 

                                                   
                                                   

                                                   
                                                  
 
                                                 
 
                                      

                                                                                                                                             
 
                                   
                                
                                                
                                                
                                                     
 
                                       
 
// license:BSD-3-Clause
// copyright-holders:Robbbert
/* Super80.cpp written by Robbbert, 2005-2009. See driver source for documentation. */

#include "emu.h"
#include "includes/super80.h"
#include "machine/z80bin.h"

/**************************** PIO ******************************************************************************/


void super80_state::pio_port_a_w(u8 data)
{
	m_keylatch = data;
	m_pio->port_b_write(pio_port_b_r()); // refresh kbd int
}

uint8_t super80_state::pio_port_b_r()
{
	uint8_t data = 0xff;

	for (int i = 0; i < 8; i++)
		if (!BIT(m_keylatch, i))
			data &= m_io_keyboard[i]->read();

	m_key_pressed = 3;

	return data;
}

/**************************** CASSETTE ROUTINES *****************************************************************/

void super80_state::cassette_motor( bool motor_state )
{
	// relay sound
	if (BIT(m_last_data, 1) != motor_state)
		m_samples->start(0, motor_state ? 0 : 1);

	if (motor_state)
		m_cassette->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
	else
		m_cassette->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);

	/* does user want to hear the sound? */
	if (BIT(m_io_config->read(), 3))
		m_cassette->change_state(CASSETTE_SPEAKER_ENABLED,CASSETTE_MASK_SPEAKER);
	else
		m_cassette->change_state(CASSETTE_SPEAKER_MUTED,CASSETTE_MASK_SPEAKER);
}

/********************************************* TIMER ************************************************/


// If normal keyboard scan has stopped, then do a scan to allow the interrupt key sequence
TIMER_DEVICE_CALLBACK_MEMBER( super80_state::timer_k )
{
	if (m_key_pressed)
		m_key_pressed--;
	else
	if (!m_key_pressed)
		m_pio->port_b_write(pio_port_b_r());
}

/* cassette load circuit
    This "emulates" U79 CD4046BCN PLL chip and U1 LM311P op-amp. U79 converts a frequency to a voltage,
    and U1 amplifies that voltage to digital levels. U1 has a trimpot connected, to set the midpoint.

    The MDS homebrew input circuit consists of 2 op-amps followed by a D-flipflop.
    The "read-any-system" cassette circuit is a CA3140 op-amp, the smarts being done in software.

    bit 0 = original system (U79 and U1)
    bit 1 = MDS fast system
    bit 2 = CA3140 */
TIMER_DEVICE_CALLBACK_MEMBER( super80_state::kansas_r )
{
	uint8_t cass_ws=0;

	m_cass_data[1]++;
	cass_ws = ((m_cassette)->input() > +0.03) ? 4 : 0;

	if (cass_ws != m_cass_data[0])
	{
		if (cass_ws) m_cass_data[3] ^= 2;       // the MDS flipflop
		m_cass_data[0] = cass_ws;
		m_cass_data[2] = ((m_cass_data[1] < 0x0d) ? 1 : 0) | cass_ws | m_cass_data[3];
		m_cass_data[1] = 0;
	}
}


TIMER_DEVICE_CALLBACK_MEMBER( super80_state::timer_h )
{
	uint8_t go_fast = 0;
	if ( (!BIT(m_portf0, 2)) | (!BIT(m_io_config->read(), 1)) )    // bit 2 of port F0 is low, OR user turned on config switch
		go_fast++; // must be 1 at boot so banking works correctly

	/* code to slow down computer to 1 MHz by halting cpu on every second frame */
	if (!go_fast)
	{
		if (!m_int_sw)
			m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);    // if going, stop it

		m_int_sw++;
		if (m_int_sw > 1)
		{
			m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);     // if stopped, start it
			m_int_sw = 0;
		}
	}
	else
	{
		if (m_int_sw < 8)                               // @2MHz, reset just once
		{
			m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
			m_int_sw = 8;                           // ...not every time
		}
	}
}

/*************************************** PRINTER ********************************************************/

/* The Super80 had an optional I/O card that plugged into the S-100 slot. The card had facility for running
    an 8-bit Centronics printer, and a serial device at 300, 600, or 1200 baud. The I/O address range
    was selectable via 4 dipswitches. The serial parameters (baud rate, parity, stop bits, etc) was
    chosen with more dipswitches. Regretably, no parameters could be set by software. Currently, the
    Centronics printer is emulated; the serial side of things may be done later, as will the dipswitches.

    The most commonly used I/O range is DC-DE (DC = centronics, DD = serial data, DE = serial control
    All the home-brew roms use this, except for super80e which uses BC-BE. */

/**************************** I/O PORTS *****************************************************************/

u8 super80v_state::port3e_r()
{
	return 0xF8 | (m_fdc->intrq_r() << 0) | (m_fdc->drq_r() << 1) | 4;
}

// UFDC board can support 4 drives; we support 2
void super80v_state::port3f_w(u8 data)
{
	// m_fdc->58(BIT(data, 0));   5/8 pin not emulated in wd_fdc
	m_fdc->enmf_w(BIT(data,1));

	floppy_image_device *floppy = nullptr;
	if (BIT(data, 2)) floppy = m_floppy0->get_device();
	if (BIT(data, 3)) floppy = m_floppy1->get_device();
	if (BIT(data, 4)) floppy = m_floppy2->get_device();
	if (BIT(data, 5)) floppy = m_floppy3->get_device();

	m_fdc->set_floppy(floppy);

	if (floppy)
	{
		floppy->mon_w(0);
		floppy->ss_w(BIT(data, 6));
	}

	m_fdc->dden_w(BIT(data, 7));
}

u8 super80_state::portf2_r()
{
	u8 data = m_io_dsw->read() & 0xf0;  // dip switches on pcb
	data |= m_cass_data[2];         // bit 0 = output of U1, bit 1 = MDS cass state, bit 2 = current wave_state
	data |= 0x08;               // bit 3 - not used
	return data;
}

void super80_state::portdc_w(u8 data)
{
	// hardware strobe driven from port select, bit 7..0 = data
	m_cent_data_out->write(data);
	m_centronics->write_strobe(0);
	m_centronics->write_strobe(1);
}


void super80_state::portf0_w(u8 data)
{
	u8 bits = data ^ m_last_data;
	m_portf0 = data;
	m_speaker->level_w(BIT(data, 3));               // bit 3 - speaker
	if (BIT(bits, 1)) cassette_motor(BIT(data, 1));  // bit 1 - cassette motor
	m_cassette->output( BIT(data, 0) ? -1.0 : +1.0);    // bit 0 - cass out

	m_last_data = data;
}


/**************************** BASIC MACHINE CONSTRUCTION ***********************************************************/

void super80_state::machine_start_common()
{
	m_cass_led.resolve();

	// register for savestates
	save_item(NAME(m_portf0));
	save_item(NAME(m_s_options));
	save_item(NAME(m_palette_index));
	save_item(NAME(m_keylatch));
	save_item(NAME(m_cass_data));
	save_item(NAME(m_key_pressed));
	save_item(NAME(m_boot_in_progress));
	save_item(NAME(m_last_data));
}

void super80_state::machine_start()
{
	machine_start_common();
	save_item(NAME(m_int_sw));
	save_item(NAME(m_vidpg));
	save_item(NAME(m_current_charset));
}

void super80v_state::machine_start()
{
	// zerofill
	m_vram = make_unique_clear<u8[]>(0x3000);
	save_pointer(NAME(m_vram), 0x3000);
	machine_start_common();
}

void super80_state::machine_reset_common()
{
	m_boot_in_progress = true;
	m_portf0 = 0; // must be 0 like real machine, or banking breaks on 32-col systems
	m_keylatch = 0xff;
	m_key_pressed = 0;
	m_palette_index = 0;

	address_space &program = m_maincpu->space(AS_PROGRAM);
	program.install_rom(0x0000, 0x0fff, m_rom);   // do it here for F3
	m_rom_shadow_tap = program.install_read_tap(0xc000, 0xcfff, "rom_shadow_r",[this](offs_t offset, u8 &data, u8 mem_mask)
	{
		if (!machine().side_effects_disabled())
		{
			// delete this tap
			m_rom_shadow_tap->remove();

			// reinstall ram over the rom shadow
			m_maincpu->space(AS_PROGRAM).install_ram(0x0000, 0x0fff, m_ram);
		}

		// return the original data
		return data;
	});
}

void super80_state::machine_reset()
{
	machine_reset_common();
	m_vidpg = 0xfe00;
}

void super80v_state::machine_reset()
{
	machine_reset_common();
}


/*-------------------------------------------------
    QUICKLOAD_LOAD_MEMBER( super80_state, super80 )
-------------------------------------------------*/

QUICKLOAD_LOAD_MEMBER(super80_state::quickload_cb)
{
	uint16_t exec_addr, start_addr, end_addr;

	// load the binary into memory
	if (z80bin_load_file(&image, m_maincpu->space(AS_PROGRAM), file_type, &exec_addr, &start_addr, &end_addr) != image_init_result::PASS)
		return image_init_result::FAIL;

	// is this file executable?
	if (exec_addr != 0xffff)
		// check to see if autorun is on
		if (BIT(m_io_config->read(), 0))
			m_maincpu->set_pc(exec_addr);

	return image_init_result::PASS;
}