summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/nitedrvr.cpp
blob: 6c9b7a34c49c8546de44317da8b69950308cd413 (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                                 





                                                                            
                
                              

                           








                                                                            
 
                              
 
                                       
                                                   
 
                                       
 
                        
                             
                              
                             
 
                                                             
                                      
 
                               
         

                                      
         
                                    
         

                                      


            
                                      

         
                              


                                                                            
              
                                                                            
 
                                          
 
                           


                 
                                                   
 
                           



                                                                            
     

























                                                                            
                                            
 
                                   
 



                                                   
 


                                                              

                              




                                                                         
                                        
                                            
                                             
                                            
                                             
                                            
                            
                                            

                                                                     
                        
                                    



                                                                            
     





























                                                                            
                                            
 
                                 
 
                                        
 


                                                    
 


                                                        










                                                    
                                                                        
                          
                                                                        
                          
                                                        
                                                                        


                                    
                                    



                                                                            
      









                                                                            
 
                                         
 


                                                                                


                                                                            
      







                                                                            
 
                                         
 
                             
 
                                 
 

                                                                                                   
 
                        
         
                                                                  

                                    


                                                                              
         
                                                                                                     


 
                                                                   
 
                                          
         
                               
                                                                                     
                                  
                                                                 
 
                                        
                 


                                                                                      


                    


                                                                                    



                 
                                    
 
                        

                              
 








                                             
 
 
                                    
 








                                
 
// license:BSD-3-Clause
// copyright-holders:Mike Balfour
/***************************************************************************

    Atari Night Driver hardware

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

#include "emu.h"
#include "includes/nitedrvr.h"
#include "sound/discrete.h"

/***************************************************************************
Steering

When D7 is high, the steering wheel has moved.
If D6 is low, it moved left.  If D6 is high, it moved right.
Be sure to keep returning a direction until steering_reset is called,
because D6 and D7 are apparently checked at different times, and a
change in-between can affect the direction you move.
***************************************************************************/

int nitedrvr_state::steering()
{
	int this_val = m_steer->read();
	int delta = this_val - m_last_steering_val;

	m_last_steering_val = this_val;

	if (delta > 128)
		delta -= 256;
	else if (delta < -128)
		delta += 256;

	// Divide by four to make our steering less sensitive
	m_steering_buf += (delta / 4);

	if (m_steering_buf > 0)
	{
		m_steering_buf--;
		m_steering_val = 0xc0;
	}
	else if (m_steering_buf < 0)
	{
		m_steering_buf++;
		m_steering_val = 0x80;
	}
	else
	{
		m_steering_val = 0x00;
	}

	return m_steering_val;
}

/***************************************************************************
steering_reset
***************************************************************************/

uint8_t nitedrvr_state::steering_reset_r()
{
	m_steering_val = 0;
	return 0;
}

void nitedrvr_state::steering_reset_w(uint8_t data)
{
	m_steering_val = 0;
}


/***************************************************************************
in0_r

Night Driver looks for the following:
    A: $00
        D4 - OPT1
        D5 - OPT2
        D6 - OPT3
        D7 - OPT4
    A: $01
        D4 - TRACK SET
        D5 - BONUS TIME ALLOWED
        D6 - VBLANK
        D7 - !TEST
    A: $02
        D4 - !GEAR 1
        D5 - !GEAR 2
        D6 - !GEAR 3
        D7 - SPARE
    A: $03
        D4 - SPARE
        D5 - DIFFICULT BONUS
        D6 - STEER A
        D7 - STEER B

Fill in the steering and gear bits in a special way.
***************************************************************************/

uint8_t nitedrvr_state::in0_r(offs_t offset)
{
	int gear = m_gears->read();

	if (gear & 0x10)                m_gear = 1;
	else if (gear & 0x20)           m_gear = 2;
	else if (gear & 0x40)           m_gear = 3;
	else if (gear & 0x80)           m_gear = 4;

	for (uint8_t i = 0; i < 4; i++)
		m_gear_sel[i] = ((m_gear == (i + 1)) ? 1 : 0);

	switch (offset & 0x03)
	{
		case 0x00:                      // No remapping necessary
			return m_dsw[0]->read();
		case 0x01:                      // No remapping necessary
			return m_dsw[1]->read();
		case 0x02:                      // Remap our gear shift
			if (m_gear == 1)
				return 0xe0;
			else if (m_gear == 2)
				return 0xd0;
			else if (m_gear == 3)
				return 0xb0;
			else
				return 0x70;
		case 0x03:                      // Remap our steering
			return (m_dsw[2]->read() | steering());
		default:
			return 0xff;
	}
}

/***************************************************************************
in1_r

Night Driver looks for the following:
    A: $00
        D6 - SPARE
        D7 - COIN 1
    A: $01
        D6 - SPARE
        D7 - COIN 2
    A: $02
        D6 - SPARE
        D7 - !START
    A: $03
        D6 - SPARE
        D7 - !ACC
    A: $04
        D6 - SPARE
        D7 - EXPERT
    A: $05
        D6 - SPARE
        D7 - NOVICE
    A: $06
        D6 - SPARE
        D7 - Special Alternating Signal
    A: $07
        D6 - SPARE
        D7 - Ground

Fill in the track difficulty switch and special signal in a special way.
***************************************************************************/

uint8_t nitedrvr_state::in1_r(offs_t offset)
{
	int port = m_in0->read();

	m_ac_line = (m_ac_line + 1) % 3;

	if (port & 0x10)                m_track = 0;
	else if (port & 0x20)           m_track = 1;
	else if (port & 0x40)           m_track = 2;

	for (uint8_t i = 0; i < 3; i++)
		m_track_sel[i] = (m_track == i ? 1 : 0);

	switch (offset & 0x07)
	{
		case 0x00:
			return ((port & 0x01) << 7);
		case 0x01:
			return ((port & 0x02) << 6);
		case 0x02:
			return ((port & 0x04) << 5);
		case 0x03:
			return ((port & 0x08) << 4);
		case 0x04:
			if (m_track == 1) return 0x80; else return 0x00;
		case 0x05:
			if (m_track == 0) return 0x80; else return 0x00;
		case 0x06:
			// TODO: fix alternating signal?
			if (m_ac_line==0) return 0x80; else return 0x00;
		case 0x07:
			return 0x00;
		default:
			return 0xff;
	}
}

/***************************************************************************
out0_w

Sound bits:

D0 = !SPEED1
D1 = !SPEED2
D2 = !SPEED3
D3 = !SPEED4
D4 = SKID1
D5 = SKID2
***************************************************************************/

void nitedrvr_state::out0_w(uint8_t data)
{
	m_discrete->write(NITEDRVR_MOTOR_DATA, data & 0x0f);  // Motor freq data
	m_discrete->write(NITEDRVR_SKID1_EN, data & 0x10);    // Skid1 enable
	m_discrete->write(NITEDRVR_SKID2_EN, data & 0x20);    // Skid2 enable
}

/***************************************************************************
out1_w

D0 = !CRASH - also drives a video invert signal
D1 = ATTRACT
D2 = Spare (Not used)
D3 = Not used?
D4 = LED START
D5 = Spare (Not used)
***************************************************************************/

void nitedrvr_state::out1_w(uint8_t data)
{
	m_led = BIT(data, 4);

	m_crash_en = data & 0x01;

	m_discrete->write(NITEDRVR_CRASH_EN, m_crash_en); // Crash enable
	m_discrete->write(NITEDRVR_ATTRACT_EN, data & 0x02);      // Attract enable (sound disable)

	if (!m_crash_en)
	{
		// Crash reset, set counter high and enable output
		m_crash_data_en = 1;
		m_crash_data = 0x0f;
		// Invert video
		m_palette->set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); // BLACK
		m_palette->set_pen_color(0, rgb_t(0xff, 0xff, 0xff)); // WHITE
	}
	m_discrete->write(NITEDRVR_BANG_DATA, m_crash_data_en ? m_crash_data : 0);    // Crash Volume
}


TIMER_DEVICE_CALLBACK_MEMBER(nitedrvr_state::crash_toggle_callback)
{
	if (m_crash_en && m_crash_data_en)
	{
		m_crash_data--;
		m_discrete->write(NITEDRVR_BANG_DATA, m_crash_data);  // Crash Volume
		if (!m_crash_data)
			m_crash_data_en = 0;    // Done counting?

		if (m_crash_data & 0x01)
		{
			// Invert video
			m_palette->set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); // BLACK
			m_palette->set_pen_color(0, rgb_t(0xff, 0xff, 0xff)); // WHITE
		}
		else
		{
			// Normal video
			m_palette->set_pen_color(0, rgb_t(0x00,0x00,0x00)); // BLACK
			m_palette->set_pen_color(1, rgb_t(0xff,0xff,0xff)); // WHITE
		}
	}
}

void nitedrvr_state::machine_start()
{
	m_led.resolve();
	m_track_sel.resolve();
	m_gear_sel.resolve();

	save_item(NAME(m_gear));
	save_item(NAME(m_track));
	save_item(NAME(m_steering_buf));
	save_item(NAME(m_steering_val));
	save_item(NAME(m_crash_en));
	save_item(NAME(m_crash_data));
	save_item(NAME(m_crash_data_en));
	save_item(NAME(m_ac_line));
	save_item(NAME(m_last_steering_val));
}

void nitedrvr_state::machine_reset()
{
	m_gear = 1;
	m_track = 0;
	m_steering_buf = 0;
	m_steering_val = 0;
	m_crash_en = 0;
	m_crash_data = 0x0f;
	m_crash_data_en = 0;
	m_ac_line = 0;
	m_last_steering_val = 0;
}