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


                                                                
                       


   
                

                    
















                         

 


                                                        
 


                                                   
 
                                                                       
 
                                                                                                               
                                                       

 
 
                                                   

                                                   
 





                                      
 


                                                   
 
                                   
 
                     
                                             

 
 

                                     

                                                            
                
 
                                                                 
 

                       











                                                                          
                                                                                               
 
                                                 
                                                               
 

                                                                          
 

                                                                          
 



                                                                          
 


                                          
 
                  
 
                                                     
 
                                       

                             
 
                 
 
                                                              

                                        
 
                                                               

                                        
 
                             
 




                                            
                               
 
                                
 
                             
                              
 
                             
 
                                          
 
                  
 
                                                              

                                        
 
                                                              

                                        
 
                             
 




                                            
                               
                                                                             
 
                                
 
                             
                              
 
                             
 
                               
 
                                          
 

                                                                            
 


                              
 


                            
 



                                                              
                                    
                    






                                                           
 


                                       
                                    
                    
                                     
 
                                                
 
                  










                                                     
                                    
 
                              
                                        
                    
                                          











                                                               







                                                                                   
                                    
 
                                
                      
 

                                                     
 

                             
                                     
 

                             
                                     
 
                                          
 




                                                                        
                                             


                             
                                                







                                                                                 
                                                    

 
                                        



                                       
                                    
 
                               

 
                                    
 
                                      
 
// license:BSD-3-Clause
// copyright-holders:Eric Smith
/*
 * mathbox.c: math box simulation (Battlezone/Red Baron/Tempest)
 *
 * Copyright Eric Smith
 *
 */

#include "emu.h"
#include "mathbox.h"


#define REG0 m_reg [0x00]
#define REG1 m_reg [0x01]
#define REG2 m_reg [0x02]
#define REG3 m_reg [0x03]
#define REG4 m_reg [0x04]
#define REG5 m_reg [0x05]
#define REG6 m_reg [0x06]
#define REG7 m_reg [0x07]
#define REG8 m_reg [0x08]
#define REG9 m_reg [0x09]
#define REGa m_reg [0x0a]
#define REGb m_reg [0x0b]
#define REGc m_reg [0x0c]
#define REGd m_reg [0x0d]
#define REGe m_reg [0x0e]
#define REGf m_reg [0x0f]


#define MB_TEST 0
#define LOG(x) do { if (MB_TEST) logerror x; } while (0)


//-------------------------------------------------
//  mathbox_device - constructor
//-------------------------------------------------

DEFINE_DEVICE_TYPE(MATHBOX, mathbox_device, "mathbox", "Atari MATHBOX")

mathbox_device::mathbox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, MATHBOX, tag, owner, clock)
{
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void mathbox_device::device_start()
{
	/* register for save states */
	save_item(NAME(m_result));
	save_item(NAME(m_reg));
}

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void mathbox_device::device_reset()
{
	m_result = 0;
	memset(m_reg, 0, sizeof(int16_t)*16);
}


WRITE8_MEMBER( mathbox_device::go_w )
{
	int32_t mb_temp;  /* temp 32-bit multiply results */
	int16_t mb_q;     /* temp used in division */
	int msb;

	LOG(("math box command %02x data %02x  ", offset, data));

	switch (offset)
	{
	case 0x00: m_result = REG0 = (REG0 & 0xff00) | data;        break;
	case 0x01: m_result = REG0 = (REG0 & 0x00ff) | (data << 8); break;
	case 0x02: m_result = REG1 = (REG1 & 0xff00) | data;        break;
	case 0x03: m_result = REG1 = (REG1 & 0x00ff) | (data << 8); break;
	case 0x04: m_result = REG2 = (REG2 & 0xff00) | data;        break;
	case 0x05: m_result = REG2 = (REG2 & 0x00ff) | (data << 8); break;
	case 0x06: m_result = REG3 = (REG3 & 0xff00) | data;        break;
	case 0x07: m_result = REG3 = (REG3 & 0x00ff) | (data << 8); break;
	case 0x08: m_result = REG4 = (REG4 & 0xff00) | data;        break;
	case 0x09: m_result = REG4 = (REG4 & 0x00ff) | (data << 8); break;

	case 0x0a: m_result = REG5 = (REG5 & 0xff00) | data;        break;
		/* note: no function loads low part of REG5 without performing a computation */

	case 0x0c: m_result = REG6 = data; break;
		/* note: no function loads high part of REG6 */

	case 0x15: m_result = REG7 = (REG7 & 0xff00) | data;        break;
	case 0x16: m_result = REG7 = (REG7 & 0x00ff) | (data << 8); break;

	case 0x1a: m_result = REG8 = (REG8 & 0xff00) | data;        break;
	case 0x1b: m_result = REG8 = (REG8 & 0x00ff) | (data << 8); break;

	case 0x0d: m_result = REGa = (REGa & 0xff00) | data;        break;
	case 0x0e: m_result = REGa = (REGa & 0x00ff) | (data << 8); break;
	case 0x0f: m_result = REGb = (REGb & 0xff00) | data;        break;
	case 0x10: m_result = REGb = (REGb & 0x00ff) | (data << 8); break;

	case 0x17: m_result = REG7; break;
	case 0x19: m_result = REG8; break;
	case 0x18: m_result = REG9; break;

	case 0x0b:

		REG5 = (REG5 & 0x00ff) | (data << 8);

		REGf = (int16_t)0xffff;
		REG4 -= REG2;
		REG5 -= REG3;

	step_048:

		mb_temp = ((int32_t) REG0) * ((int32_t) REG4);
		REGc = mb_temp >> 16;
		REGe = mb_temp & 0xffff;

		mb_temp = ((int32_t) -REG1) * ((int32_t) REG5);
		REG7 = mb_temp >> 16;
		mb_q = mb_temp & 0xffff;

		REG7 += REGc;

		/* rounding */
		REGe = (REGe >> 1) & 0x7fff;
		REGc = (mb_q >> 1) & 0x7fff;
		mb_q = REGc + REGe;
		if (mb_q < 0)
			REG7++;

		m_result = REG7;

		if (REGf < 0)
			break;

		REG7 += REG2;

		/* fall into command 12 */

	case 0x12:

		mb_temp = ((int32_t) REG1) * ((int32_t) REG4);
		REGc = mb_temp >> 16;
		REG9 = mb_temp & 0xffff;

		mb_temp = ((int32_t) REG0) * ((int32_t) REG5);
		REG8 = mb_temp >> 16;
		mb_q = mb_temp & 0xffff;

		REG8 += REGc;

		/* rounding */
		REG9 = (REG9 >> 1) & 0x7fff;
		REGc = (mb_q >> 1) & 0x7fff;
		REG9 += REGc;
		if (REG9 < 0)
			REG8++;
		REG9 <<= 1;  /* why? only to get the desired load address? */

		m_result = REG8;

		if (REGf < 0)
			break;

		REG8 += REG3;

		REG9 &= 0xff00;

		/* fall into command 13 */

	case 0x13:
		LOG(("\nR7: %04x  R8: %04x  R9: %04x\n", REG7, REG8, REG9));

		REGc = REG9;
		mb_q = REG8;
		goto step_0bf;

	case 0x14:
		REGc = REGa;
		mb_q = REGb;

	step_0bf:
		REGe = REG7 ^ mb_q;  /* save sign of result */
		REGd = mb_q;
		if (mb_q >= 0)
			mb_q = REGc;
		else
		{
			REGd = - mb_q - 1;
			mb_q = - REGc - 1;
			if ((mb_q < 0) && ((mb_q + 1) < 0))
				REGd++;
			mb_q++;
		}

	/* step 0c9: */
		/* REGc = abs (REG7) */
		if (REG7 >= 0)
			REGc = REG7;
		else
			REGc = -REG7;

		REGf = REG6;  /* step counter */

		do
		{
			REGd -= REGc;
			msb = ((mb_q & 0x8000) != 0);
			mb_q <<= 1;
			if (REGd >= 0)
				mb_q++;
			else
				REGd += REGc;
			REGd <<= 1;
			REGd += msb;
		}
		while (--REGf >= 0);

		if (REGe >= 0)
			m_result = mb_q;
		else
			m_result = - mb_q;
		break;

	case 0x11:
		REG5 = (REG5 & 0x00ff) | (data << 8);
		REGf = 0x0000;  /* do everything in one step */
		goto step_048;
		//break; // never reached

	case 0x1c:
		/* window test? */
		REG5 = (REG5 & 0x00ff) | (data << 8);
		do
		{
			REGe = (REG4 + REG7) >> 1;
			REGf = (REG5 + REG8) >> 1;
			if ((REGb < REGe) && (REGf < REGe) && ((REGe + REGf) >= 0))
			{ REG7 = REGe; REG8 = REGf; }
			else
			{ REG4 = REGe; REG5 = REGf; }
		}
		while (--REG6 >= 0);

		m_result = REG8;
		break;

	case 0x1d:
		REG3 = (REG3 & 0x00ff) | (data << 8);

		REG2 -= REG0;
		if (REG2 < 0)
			REG2 = -REG2;

		REG3 -= REG1;
		if (REG3 < 0)
			REG3 = -REG3;

		/* fall into command 1e */

	case 0x1e:
		/* result = max (REG2, REG3) + 3/8 * min (REG2, REG3) */
		if (REG3 >= REG2)
		{ REGc = REG2; REGd = REG3; }
		else
		{ REGd = REG2; REGc = REG3; }
		REGc >>= 2;
		REGd += REGc;
		REGc >>= 1;
		m_result = REGd = (REGc + REGd);
		break;

	case 0x1f:
		logerror("math box function 0x1f\n");
		/* $$$ do some computation here (selftest? signature analysis? */
		break;
	}

	LOG(("  result %04x\n", m_result & 0xffff));
}

READ8_MEMBER( mathbox_device::status_r )
{
	return 0x00; /* always done! */
}

READ8_MEMBER( mathbox_device::lo_r )
{
	return m_result & 0xff;
}

READ8_MEMBER( mathbox_device::hi_r )
{
	return (m_result >> 8) & 0xff;
}