summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/seibucop_cmd.hxx
blob: 51f486c1bc720fb55f6cadcff02df42939f3f0e6 (plain) (tree)
1
2
3


                                                                                   




















                                                                                                                                                                                
                                                               
 
                                                                                    

                                                                                    


                











                                                                                                                                                                                
                                                               
 


                                                                                                                                                                                   
 
















                                                                                                                                                                                              






                                                                                                  
                                                              

                                                                              
 
                                                                                  
                                             

 
                                                                             


                                                                                                       
 
                       
 



                                     
            
         


                                                                                
 
                                  







                                                                                             
                                                                














                                                                                                                                                                                
                                                               























                                                                                                                                                                                
                                                               











                                                                                                                                                              
                                                                              


                                                                                                       
 

                       







                                                                              
 
                                  


                  
                                                                                     


                            
                                      



                                                                             










                                                                                                                                                              
                                                               













                                                                                                   
 
                          
                                                                                     





                                                                                                                                                                                
                                                               
 
                                                      







                                                                         
                                                        







                                                                                      


                                           
      
 
                                                                                  





                                                                                                                                                                                
                                                               
















                                                                                                     
                                                               








                                                                                                     
                                                               








                                                                                                                                                                        
                                                               



                                  

                                                                              

























                                                     
 







                                                                                                                                                        
                                                                                                                                              



                                 

                                                                              





































                                                                                                                                                        
                                                                      
 
                     
                             
                   



                                                                                                                               

                                                                              




                                                                          

                                                      

                                                                                           
 



                                                                                                                     
 
                                                                                                                          












                                                                                                    
                                                                           








                                                                                                                                                                                
                                                               















                                                                                                                                                                                
                                                               





































                                                                                                                                              
                                                               









                                                                                                                        
                                                               









                                                                                                                                                                       
                                                               











                                                                                                                                                                       
                                                               











                                                                                                                                           



                                                                                                                                           
                                                                      
 
                     


                                    


                                
                                                            

                                                                                                             
 

                                                                                  
 



                                                               
 










                                                                                                          
 



                                                                                                          
 
                                                                                                     






                                                                                      



                                                                              
                                                                   










                                                                                                    
                                                                      
 
                                                                                         

                                                                          










                                                                                                                      
                                                                      
 
                     
                

                                         

































                                                                                                                                             
                                                     
                                                                      
 


                                                                                                       
 
                       

                






                                                                                
 

                                  
 


                                                                                     
 


                                                              














                                                                                                     
                                                               








                                                                                                    






                                                                                                  
                                                               



              



                                                  
                                                                      


                                                                                                        
 












                                                                                
 



                                                                              
                                                                      











                                                                         
                                                                      

































                                                                                           
                                                          
                                                               









                                                                                                   
                                                               



                                                                                                                           

      
// license:LGPL-2.1+
// copyright-holders:Olivier Galibert, Angelo Salese, David Haywood, Tomasz Slanina

/* Main COP functionality */

// notes about tables:
// (TABLENOTE1)
// in all but one case the upload table position (5-bits) is the SAME as the upper 5-bits of the 'trigger value'
// the exception to this rule is program 0x18 uploads on zeroteam
//  in this case you can see that the 'trigger' value upper bits are 0x0f, this would be potentially interesting if it were used (but it isn't)
//  18 - c480 ( 18) (  480) :  (080, 882, 000, 000, 000, 000, 000, 000)  a     ff00   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk)
//  18 - 7c80 ( 0f) (  480) :  (080, 882, 000, 000, 000, 000, 000, 000)  a     ff00   (zeroteam, xsedae)

// It is unknown if the lower 11 bits uploaded as part of the 'trigger' value to the table are used during execution.
// When the actual trigger is written these bits can be different to the upload and for the written value we know they give extended
// meanings to the commands (eg. signs swapped in operations - for program 0x01 (0905) Zero Team writes 0904 (lowest bit different to uploaded
// value) to negate the logic

/*

## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
00 - 0205 ( 00) (  205) :  (188, 282, 082, b8e, 98e, 000, 000, 000)  6     ffeb   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
00 - 0105 ( 00) (  105) :  (180, 2e0, 0a0, 000, 000, 000, 000, 000)  6     fffb   (zeroteamsr)
*/
void raiden2cop_device::execute_0205(int offset, uint16_t data)
{
	int ppos =        m_host_space->read_dword(cop_regs[0] + 0x04 + offset * 4);
	int npos = ppos + m_host_space->read_dword(cop_regs[0] + 0x10 + offset * 4);
	int delta = (npos >> 16) - (ppos >> 16);
#if LOG_Move0205
	// ...
#endif
	m_host_space->write_dword(cop_regs[0] + 4 + offset * 4, npos);
	cop_write_word(cop_regs[0] + 0x1e + offset * 4, cop_read_word(cop_regs[0] + 0x1e + offset * 4) + delta);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
01 - 0905 ( 01) (  105) :  (194, 288, 088, 000, 000, 000, 000, 000)  6     fbfb   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
01 - 0b05 ( 01) (  305) :  (180, 2e0, 0a0, 182, 2e0, 0c0, 000, 000)  6     ffdb   (zeroteamsr)
*/

// triggered with 0904 0905

void raiden2cop_device::execute_0904(int offset, uint16_t data)
{
#if LOG_Move0905
	printf("cmd %04x: %08x %08x [%08x]\n",data, m_host_space->read_dword(cop_regs[0] + 16 + offset * 4),m_host_space->read_dword(cop_regs[0] + 0x28 + offset * 4),cop_regs[0]);
#endif

	if (data&0x0001)
		m_host_space->write_dword(cop_regs[0] + 16 + offset * 4, m_host_space->read_dword(cop_regs[0] + 16 + offset * 4) + m_host_space->read_dword(cop_regs[0] + 0x28 + offset * 4));
	else /* X Se Dae and Zero Team uses this variant */
		m_host_space->write_dword(cop_regs[0] + 16 + offset * 4, m_host_space->read_dword(cop_regs[0] + 16 + offset * 4) - m_host_space->read_dword(cop_regs[0] + 0x28 + offset * 4));
}




/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
02 - 138e ( 02) (  38e) :  (984, aa4, d82, aa2, 39b, b9a, b9a, b9a)  5     bf7f   (legionna, heatbrl)
02 - 138e ( 02) (  38e) :  (984, aa4, d82, aa2, 39b, b9a, b9a, a9a)  5     bf7f   (cupsoc, grainbow, godzilla, denjinmk)
02 - 130e ( 02) (  30e) :  (984, aa4, d82, aa2, 39b, b9a, b9a, a9a)  5     bf7f   (raiden2, raidendx, zeroteam, xsedae)
*/

// triggered with 130e, 138e
/*
TAD games uses a variation of this:
[:raiden2cop] COPDIS: 138e s=10 f1=0 l=8 f2=0e 5 bf7f 17 b9a 17.0.1a [:raiden2cop] addmem16 34(r0)
instead of
[:raiden2cop] COPDIS: 130e s=10 f1=0 l=7 f2=0e 5 bf7f 17 a9a 15.0.1a [:raiden2cop] sub32 34(r0)
cop_angle is actually Y flipped when this is called

TODO: it really needs actual opcode fetching from macro tables
*/
void raiden2cop_device::execute_130e(int offset, uint16_t data, bool is_yflip)
{
	// this can't be right, or bits 15-12 from mask have different meaning ...
	execute_338e(offset, data, is_yflip);
}

void raiden2cop_device::LEGACY_execute_130e_cupsoc(int offset, uint16_t data)
{
	int dy = m_host_space->read_dword(cop_regs[1] + 4) - m_host_space->read_dword(cop_regs[0] + 4);
	int dx = m_host_space->read_dword(cop_regs[1] + 8) - m_host_space->read_dword(cop_regs[0] + 8);

	cop_status = 7;

	if (!dx) {
		cop_status |= 0x8000;
		cop_angle = 0;
	}
	else
	{
		cop_angle = (int)(atan(double(dy) / double(dx)) * 128.0 / M_PI);
		if (dx < 0)
			cop_angle += 0x80;

		cop_angle &= 0xff;
	}

	m_LEGACY_r0 = dy;
	m_LEGACY_r1 = dx;

	//printf("%d %d %f %04x\n",dx,dy,atan(double(dy)/double(dx)) * 128 / M_PI,cop_angle);

	if (data & 0x80)
		cop_write_byte(cop_regs[0] + (0x34), cop_angle);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
03 - 1905 ( 03) (  105) :  (994, a88, 088, 000, 000, 000, 000, 000)  6     fbfb   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
*/

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
04 - 2288 ( 04) (  288) :  (f8a, b8a, 388, b9c, b9a, a9a, 000, 000)  5     f5df   (legionna, heatbrl)
04 - 2288 ( 04) (  288) :  (f8a, b8a, 388, b9a, b9a, a9a, 000, 000)  5     f5df   (cupsoc, grainbow, godzilla, denjinmk)
04 - 2208 ( 04) (  208) :  (f8a, b8a, 388, b9a, b9a, a9a, 000, 000)  5     f5df   (raiden2, raidendx, zeroteam, xsedae)
*/

// also triggered with 0x2208
void raiden2cop_device::execute_2288(int offset, uint16_t data)
{
	int dx = m_host_space->read_word(cop_regs[0] + 0x12);
	int dy = m_host_space->read_word(cop_regs[0] + 0x16);

	if (!dy) {
		cop_status |= 0x8000;
		cop_angle = 0;
	}
	else {
		cop_angle = (int)(atan(double(dx) / double(dy)) * 128 / M_PI);
		if (dy < 0)
			cop_angle += 0x80;
	}

	if (data & 0x0080) {
		m_host_space->write_byte(cop_regs[0] + 0x34, cop_angle);
	}
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
05 - 2a05 ( 05) (  205) :  (9af, a82, 082, a8f, 18e, 000, 000, 000)  6     ebeb   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
*/

void raiden2cop_device::execute_2a05(int offset, uint16_t data)
{
	int delta = m_host_space->read_word(cop_regs[1] + 0x1e + offset * 4);
	m_host_space->write_dword(cop_regs[0] + 4 + 2 + offset * 4, m_host_space->read_word(cop_regs[0] + 4 + 2 + offset * 4) + delta);
	m_host_space->write_dword(cop_regs[0] + 0x1e + offset * 4, m_host_space->read_word(cop_regs[0] + 0x1e + offset * 4) + delta);
}


/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
06 - 338e ( 06) (  38e) :  (984, aa4, d82, aa2, 39c, b9c, b9c, a9a)  5     bf7f   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx)
06 - 330e ( 06) (  30e) :  (984, aa4, d82, aa2, 39c, b9c, b9c, a9a)  5     bf7f   (zeroteam, xsedae)
*/
void raiden2cop_device::execute_338e(int offset, uint16_t data, bool is_yflip)
{
	int dx = m_host_space->read_dword(cop_regs[1] + 4) - m_host_space->read_dword(cop_regs[0] + 4);
	int dy = m_host_space->read_dword(cop_regs[1] + 8) - m_host_space->read_dword(cop_regs[0] + 8);

	cop_status = 7;

	if (!dy) {
		cop_status |= 0x8000;
		cop_angle = 0;
	}
	else {
		cop_angle = (int)(atan(double(dx) / double(dy)) * 128 / M_PI);
		if (dy < 0)
			cop_angle += 0x80;

		cop_angle &= 0xff;
	}

#if LOG_Phytagoras
	printf("cmd %04x: dx = %d dy = %d angle = %02x %04x\n",data,dx,dy,cop_angle);
#endif

	if (data & 0x0080) {
		// TODO: byte or word?
		if(is_yflip == true)
			cop_write_byte(cop_regs[0] + 0x34, cop_angle ^ 0x80);
		else
			cop_write_byte(cop_regs[0] + 0x34, cop_angle);
	}
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
07 - 3bb0 ( 07) (  3b0) :  (f9c, b9c, b9c, b9c, b9c, b9c, b9c, 99c)  4     007f   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx,
07 - 3b30 ( 07) (  330) :  (f9c, b9c, b9c, b9c, b9c, b9c, b9c, 99c)  4     007f   (zeroteam, xsedae)
*/

// triggered with 0x39b0, 0x3b30, 0x3bb0

void raiden2cop_device::execute_3b30(int offset, uint16_t data)
{
	/* TODO: these are actually internally loaded via 0x130e command */
	int dx, dy;

	dx = m_host_space->read_dword(cop_regs[1] + 4) - m_host_space->read_dword(cop_regs[0] + 4);
	dy = m_host_space->read_dword(cop_regs[1] + 8) - m_host_space->read_dword(cop_regs[0] + 8);

	dx = dx >> 16;
	dy = dy >> 16;
	cop_dist = sqrt((double)(dx*dx + dy*dy));

#if LOG_Phytagoras
	printf("cmd %04x: dx = %d dy = %d dist = %08x \n",data,dx >> 16,dy >> 16,cop_dist);
#endif

	if (data & 0x0080)
		cop_write_word(cop_regs[0] + (data & 0x200 ? 0x3a : 0x38), cop_dist);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
08 - 42c2 ( 08) (  2c2) :  (f9a, b9a, b9c, b9c, b9c, 29c, 000, 000)  5     fcdd   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
*/
void raiden2cop_device::execute_42c2(int offset, uint16_t data)
{
	int div = cop_read_word(cop_regs[0] + (0x36));

#if LOG_Division
	printf("cmd %04x: div = %04x scale = %04x\n",data,div,cop_scale);
#endif

	if (!div)
	{
		cop_status |= 0x8000;
		cop_write_word(cop_regs[0] + (0x38), 0);
		return;
	}

	/* TODO: bits 5-6-15 */
	cop_status = 7;

#if LOG_Division
	printf("res = %04x dist %04x\n",(cop_dist << (5 - cop_scale)) / div,cop_dist);

//  if(div & 0x8000)
//      machine().debugger().debug_break();
#endif

	cop_write_word(cop_regs[0] + (0x38), (cop_dist << (5 - cop_scale)) / div);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
09 - 4aa0 ( 09) (  2a0) :  (f9a, b9a, b9c, b9c, b9c, 99b, 000, 000)  5     fcdd   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
*/
void raiden2cop_device::execute_4aa0(int offset, uint16_t data)
{
	int div = m_host_space->read_word(cop_regs[0] + (0x38));
	if (!div)
		div = 1;

	/* TODO: bits 5-6-15 */
	cop_status = 7;

	m_host_space->write_word(cop_regs[0] + (0x36), (cop_dist << (5 - cop_scale)) / div);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
0a - 5105 ( 0a) (  105) :  (a80, 984, 082, 000, 000, 000, 000, 000)  5     fefb   (cupsoc, grainbow)
0a - 5205 ( 0a) (  205) :  (180, 2e0, 3a0, 0a0, 3a0, 000, 000, 000)  6     fff7   (raiden2, raidendx)
0a - 5105 ( 0a) (  105) :  (180, 2e0, 0a0, 000, 000, 000, 000, 000)  6     fffb   (zeroteam, xsedae)
*/
void raiden2cop_device::execute_5205(int offset, uint16_t data)
{
	m_host_space->write_dword(cop_regs[1], m_host_space->read_dword(cop_regs[0]));
}
/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
0b - 5905 ( 0b) (  105) :  (9c8, a84, 0a2, 000, 000, 000, 000, 000)  5     fffb   (cupsoc, grainbow)
0b - 5a05 ( 0b) (  205) :  (180, 2e0, 3a0, 0a0, 3a0, 000, 000, 000)  6     fff7   (raiden2, raidendx)
0b - 5a85 ( 0b) (  285) :  (180, 2e0, 0a0, 182, 2e0, 0c0, 3c0, 3c0)  6     ffdb   (zeroteam, xsedae)
*/
void raiden2cop_device::execute_5a05(int offset, uint16_t data)
{
	m_host_space->write_dword(cop_regs[1], m_host_space->read_dword(cop_regs[0]));
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
0c - 6200 ( 0c) (  200) :  (380, 39a, 380, a80, 29a, 000, 000, 000)  8     f3e7   (legionn, heatbrla, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
0c - 6200 ( 0c) (  200) :  (3a0, 3a6, 380, aa0, 2a6, 000, 000, 000)  8     f3e7   (cupsoc)
*/
void raiden2cop_device::execute_6200(int offset, uint16_t data)
{
	int primary_reg = 0;
	int primary_offset = 0x34;

	uint8_t angle = cop_read_byte(cop_regs[primary_reg] + primary_offset);
	uint16_t flags = cop_read_word(cop_regs[primary_reg]);
	cop_angle_target &= 0xff;
	cop_angle_step &= 0xff;
	flags &= ~0x0004;
	int delta = angle - cop_angle_target;
	if (delta >= 128)
		delta -= 256;
	else if (delta < -128)
		delta += 256;
	if (delta < 0) {
		if (delta >= -cop_angle_step) {
			angle = cop_angle_target;
			flags |= 0x0004;
		}
		else
			angle += cop_angle_step;
	}
	else {
		if (delta <= cop_angle_step) {
			angle = cop_angle_target;
			flags |= 0x0004;
		}
		else
			angle -= cop_angle_step;
	}

	cop_write_word(cop_regs[primary_reg], flags);

	if (!m_host_endian)
		cop_write_byte(cop_regs[primary_reg] + primary_offset, angle);
	else // angle is a byte, but grainbow (cave mid-boss) is only happy with write-word, could be more endian weirdness, or it always writes a word?
		cop_write_word(cop_regs[primary_reg] + primary_offset, angle);

}


void raiden2cop_device::LEGACY_execute_6200(int offset, uint16_t data) // this is for cupsoc, different sequence, works on different registers
{
	int primary_reg = 1;
	int primary_offset = 0xc;

	uint8_t angle = cop_read_byte(cop_regs[primary_reg] + primary_offset);
	uint16_t flags = cop_read_word(cop_regs[primary_reg]);
	cop_angle_target &= 0xff;
	cop_angle_step &= 0xff;
	flags &= ~0x0004;
	int delta = angle - cop_angle_target;
	if (delta >= 128)
		delta -= 256;
	else if (delta < -128)
		delta += 256;
	if (delta < 0) {
		if (delta >= -cop_angle_step) {
			angle = cop_angle_target;
			flags |= 0x0004;
		}
		else
			angle += cop_angle_step;
	}
	else {
		if (delta <= cop_angle_step) {
			angle = cop_angle_target;
			flags |= 0x0004;
		}
		else
			angle -= cop_angle_step;
	}

	cop_write_word(cop_regs[primary_reg], flags);

	if (!m_host_endian)
		cop_write_byte(cop_regs[primary_reg] + primary_offset, angle);
	else // angle is a byte, but grainbow (cave mid-boss) is only happy with write-word, could be more endian weirdness, or it always writes a word?
		cop_write_word(cop_regs[primary_reg] + primary_offset, angle);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
0d - 6880 ( 0d) (  080) :  (b80, ba0, 000, 000, 000, 000, 000, 000)  a     fff3   (legionna, heatbrl, cupsoc, godzilla, denjinmk)
0d - 6980 ( 0d) (  180) :  (b80, ba0, 000, 000, 000, 000, 000, 000)  a     fff3   (grainbow, zeroteam, xsedae)
*/
void raiden2cop_device::LEGACY_execute_6980(int offset, uint16_t data)
{
	uint8_t offs;
//  int abs_x, abs_y, rel_xy;
	int rel_xy;

	offs = (offset & 3) * 4;

	/* TODO: I really suspect that following two are actually taken from the 0xa180 macro command then internally loaded */
//  abs_x = m_host_space->read_word(cop_regs[0] + 8) - m_cop_sprite_dma_abs_x;
//  abs_y = m_host_space->read_word(cop_regs[0] + 4) - m_cop_sprite_dma_abs_y;
	rel_xy = m_host_space->read_word(m_cop_sprite_dma_src + 4 + offs);

	//if(rel_xy & 0x0706)
	//  printf("sprite rel_xy = %04x\n",rel_xy);

	m_sprite_dma_rel_x = (rel_xy & 0xff);
	m_sprite_dma_rel_y = ((rel_xy & 0xff00) >> 8);
//  m_sprite_dma_rel_x = (rel_xy & 0x78) + (abs_x)-((rel_xy & 0x80) ? 0x80 : 0);
//  m_sprite_dma_rel_y = ((rel_xy & 0x7800) >> 8) + (abs_y)-((rel_xy & 0x8000) ? 0x80 : 0);

//  if (rel_xy & 1)
//      m_host_space->write_word(cop_regs[4] + offs + 4, 0xc0 + abs_x - (rel_xy & 0xf8));
//  else
//      m_host_space->write_word(cop_regs[4] + offs + 4, (((rel_xy & 0x78) + (abs_x)-((rel_xy & 0x80) ? 0x80 : 0))));

//  m_host_space->write_word(cop_regs[4] + offs + 6, (((rel_xy & 0x7800) >> 8) + (abs_y)-((rel_xy & 0x8000) ? 0x80 : 0)));
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
0e - 7100 ( 0e) (  100) :  (b80, a80, b80, 000, 000, 000, 000, 000)  8     fdfd   (zeroteam, xsedae)
*/

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
0f - 7905 ( 0f) (  105) :  (1a2, 2c2, 0a2, 000, 000, 000, 000, 000)  6     fffb   (cupsoc, grainbow)
0f - 7e05 ( 0f) (  605) :  (180, 282, 080, 180, 282, 000, 000, 000)  6     fffb   (raidendx)
*/

void raiden2cop_device::execute_7e05(int offset, uint16_t data) // raidendx
{
	m_host_space->write_byte(0x470, m_host_space->read_byte(cop_regs[4]));
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
10 - 8100 ( 10) (  100) :  (b9a, b88, 888, 000, 000, 000, 000, 000)  7     fdfb   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
*/

void raiden2cop_device::execute_8100(int offset, uint16_t data)
{
	int raw_angle = (cop_read_word(cop_regs[0] + (0x34)) & 0xff);
	double angle = raw_angle * M_PI / 128;
	double amp = (65536 >> 5)*(cop_read_word(cop_regs[0] + (0x36)) & 0xff);
	int res;
	// TODO: up direction needs to be doubled, happens on bootleg too, why is that?
	if (raw_angle == 0xc0)
		amp *= 2;
	res = int(amp*sin(angle)) << cop_scale;
	m_host_space->write_dword(cop_regs[0] + 16, res);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
11 - 8900 ( 11) (  100) :  (b9a, b8a, 88a, 000, 000, 000, 000, 000)  7     fdfb   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
*/
void raiden2cop_device::execute_8900(int offset, uint16_t data)
{
	int raw_angle = (cop_read_word(cop_regs[0] + (0x34)) & 0xff);
	double angle = raw_angle * M_PI / 128;
	double amp = (65536 >> 5)*(cop_read_word(cop_regs[0] + (0x36)) & 0xff);
	int res;
	// TODO: left direction needs to be doubled, happens on bootleg too, why is that?
	if (raw_angle == 0x80)
		amp *= 2;
	res = int(amp*cos(angle)) << cop_scale;
	m_host_space->write_dword(cop_regs[0] + 20, res);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
12 - 9180 ( 12) (  180) :  (b80, b94, b94, 894, 000, 000, 000, 000)  7     f8f7   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk)
12 - 9100 ( 12) (  100) :  (b80, b94, 894, 000, 000, 000, 000, 000)  7     fefb   (raiden2, raidendx)
12 - 9100 ( 12) (  100) :  (b80, b94, b94, 894, 000, 000, 000, 000)  7     f8f7   (zeroteam, xsedae)
*/
// Unused code suggests this may be an alternate sine function: the longword result at cop_regs[0] + 0x28 is doubled when the angle is 0xC0.

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
13 - 9980 ( 13) (  180) :  (b80, b96, b96, 896, 000, 000, 000, 000)  7     f8f7   (legionna, heatbrl)
13 - 9980 ( 13) (  180) :  (b80, b94, b94, 896, 000, 000, 000, 000)  7     f8f7   (cupsoc, grainbow, godzilla, denjinmk)
13 - 9900 ( 13) (  100) :  (b80, b94, 896, 000, 000, 000, 000, 000)  7     fefb   (raiden2, raidendx)
13 - 9900 ( 13) (  100) :  (b80, b94, b94, 896, 000, 000, 000, 000)  7     f8f7   (zeroteam, xsedae)
*/
// Unused code suggests this may be an alternate cosine function: the longword result at cop_regs[0] + 0x2C is doubled when the angle is 0x80.

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
14 - a180 ( 14) (  180) :  (b80, b82, b84, b86, 000, 000, 000, 000)  0     ffff   (legionna, cupsoc, godzilla, denjinmk)
14 - a100 ( 14) (  100) :  (b80, b82, b84, b86, 000, 000, 000, 000)  0     ffff   (heatbrl, zeroteam, xsedae)
14 - a180 ( 14) (  180) :  (b80, b82, b84, b86, 000, 000, 000, 000)  0     02ff   (grainbow)
14 - a100 ( 14) (  100) :  (b80, b82, b84, b86, 000, 000, 000, 000)  0     00ff   (raiden2, raidendx)
*/

// the last value (ffff / 02ff / 00ff depending on game) might be important here as they've been intentionally changed for the different games
void raiden2cop_device::execute_a100(int offset, uint16_t data)
{
	cop_collision_read_pos(0, cop_regs[0], data & 0x0080);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
15 - a980 ( 15) (  180) :  (ba0, ba2, ba4, ba6, 000, 000, 000, 000)  f     ffff   (legionna, cupsoc, godzilla, denjinmk)
15 - a900 ( 15) (  100) :  (ba0, ba2, ba4, ba6, 000, 000, 000, 000)  f     ffff   (heatbrl, zeroteam), xsedae
15 - a980 ( 15) (  180) :  (ba0, ba2, ba4, ba6, 000, 000, 000, 000)  f     02ff   (grainbow)
15 - a900 ( 15) (  100) :  (ba0, ba2, ba4, ba6, 000, 000, 000, 000)  f     00ff   (raiden2, raidendx)*/
void raiden2cop_device::execute_a900(int offset, uint16_t data)
{
	cop_collision_read_pos(1, cop_regs[1], data & 0x0080);
}


/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
16 - b100 ( 16) (  100) :  (b40, bc0, bc2, 000, 000, 000, 000, 000)  9     ffff   (legionna, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
16 - b080 ( 16) (  080) :  (b40, bc0, bc2, 000, 000, 000, 000, 000)  9     ffff   (heatbrl)
*/
void raiden2cop_device::execute_b100(int offset, uint16_t data)
{
	cop_collision_update_hitbox(data, 0, cop_regs[2]);
}




/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
17 - b900 ( 17) (  100) :  (b60, be0, be2, 000, 000, 000, 000, 000)  6     ffff   (legionna, cupsoc, grainbow, godzilla, denjinmk, raiden2, raidendx, zeroteam, xsedae)
17 - b880 ( 17) (  080) :  (b60, be0, be2, 000, 000, 000, 000, 000)  6     ffff   (heatbrl)
*/
void raiden2cop_device::execute_b900(int offset, uint16_t data)
{
	cop_collision_update_hitbox(data, 1, cop_regs[3]);
}



/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
18 - c480 ( 18) (  480) :  (080, 882, 000, 000, 000, 000, 000, 000)  a     ff00   (legionna, heatbrl, cupsoc, grainbow, godzilla, denjinmk)
18 - 7c80 ( 0f) (  480) :  (080, 882, 000, 000, 000, 000, 000, 000)  a     ff00   (zeroteam, xsedae)
*/

// SD Gundam single step sprite DMA
// Notes of interest:
// - bit 0 of rel_x is enabled at stage 2 boss for the flipped ray but seems left-over;
// - stage 3 midboss has some garbage sprites, that's because game incorrectly sets up a size of 8 for one transfer, prolly more left-over;
void raiden2cop_device::LEGACY_execute_c480(int offset, uint16_t data)
{
	uint8_t offs;
	uint16_t sprite_info;
	uint16_t sprite_x, sprite_y;
	int abs_x, abs_y;

	offs = (offset & 3) * 4;

	// TODO: bit 16 of sprite param may go there as well
	sprite_info = m_host_space->read_word(m_cop_sprite_dma_src + offs) + (m_cop_sprite_dma_param & 0x3f);
	m_host_space->write_word(cop_regs[4] + offs + 0, sprite_info);

	abs_x = m_host_space->read_word(cop_regs[0] + 8) - m_cop_sprite_dma_abs_x;
	abs_y = m_host_space->read_word(cop_regs[0] + 4) - m_cop_sprite_dma_abs_y;

	const u8 fx     =  (sprite_info & 0x4000) >> 14;
	const u8 fy     =  (sprite_info & 0x2000) >> 13;
	const u8 dx     = ((sprite_info & 0x1c00) >> 10) + 1;
	//const u8 dy     = ((sprite_info & 0x0380) >> 7)  + 1;

	if (fx)
	{
		sprite_x = (0x100 - (dx*16));
		sprite_x += (abs_x)-(m_sprite_dma_rel_x & 0x78);
		if (m_sprite_dma_rel_x & 0x80)
			sprite_x -= 0x80;
		else
			sprite_x -= 0x100;
	}
	else
		sprite_x = (m_sprite_dma_rel_x & 0x78) + (abs_x)-((m_sprite_dma_rel_x & 0x80) ? 0x80 : 0);

	if (fy)
		sprite_y = (abs_y)+((m_sprite_dma_rel_y & 0x80) ? 0x80 : 0)-(m_sprite_dma_rel_y & 0x78);
	else
		sprite_y = (m_sprite_dma_rel_y & 0x78) + (abs_y)-((m_sprite_dma_rel_y & 0x80) ? 0x80 : 0);

	// 3rd midboss enables this bit for the sections that should be covered by the ground layers,
	// effectively changing the priority value to 2
	if (m_cop_sprite_dma_param & 0x00020000)
	{
		uint16_t sprite_pri = m_host_space->read_word(cop_regs[4] + offs + 2);
		sprite_pri |= 0x8000;
		m_host_space->write_word(cop_regs[4] + offs + 2, sprite_pri);
	}

	// save into internal clip register, cfr. increment DMA register $410
	m_sprite_dma_x_clip = sprite_x;
	m_host_space->write_word(cop_regs[4] + offs + 4, m_sprite_dma_x_clip);
	m_host_space->write_word(cop_regs[4] + offs + 6, sprite_y);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
19 - cb8f ( 19) (  38f) :  (984, aa4, d82, aa2, 39b, b9a, b9a, a9f)  5     bf7f   (cupsoc, grainbow)
*/

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
1a - d104 ( 1a) (  104) :  (ac2, 9e0, 0a2, 000, 000, 000, 000, 000)  5     fffb   (cupsoc, grainbow)
*/
void raiden2cop_device::LEGACY_execute_d104(int offset, uint16_t data)
{
	uint16_t *ROM = (uint16_t *)machine().root_device().memregion("maincpu")->base();
	uint32_t rom_addr = (m_cop_rom_addr_hi << 16 | m_cop_rom_addr_lo);
	uint16_t rom_data = ROM[rom_addr / 2];

	/* writes to some unemulated COP registers, then puts the result in here, adding a parameter taken from ROM */
	//m_host_space->write_word(cop_regs[0]+(0x44 + offset * 4), rom_data);

	logerror("%04x%04x %04x %04x\n", m_cop_rom_addr_hi, m_cop_rom_addr_lo, m_cop_precmd, rom_data);
}
/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
1b - dde5 ( 1b) (  5e5) :  (f80, aa2, 984, 0c2, 000, 000, 000, 000)  5     7ff7   (cupsoc, grainbow)
*/

void raiden2cop_device::LEGACY_execute_dde5(int offset, uint16_t data)
{
	uint8_t offs;
	int div;
	int16_t dir_offset;
	//              int16_t offs_val;

	/* TODO: [4-7] could be mirrors of [0-3] (this is the only command so far that uses 4-7 actually)*/
	/* ? 0 + [4] */
	/* sub32 4 + [5] */
	/* write16h 8 + [4] */
	/* addmem16 4 + [6] */

	// these two are obvious ...
	// 0xf x 16 = 240
	// 0x14 x 16 = 320
	// what are these two instead? scale factor? offsets? (edit: offsets to apply from the initial sprite data)
	// 0xfc69 ?
	// 0x7f4 ?
	//printf("%08x %08x %08x %08x %08x %08x %08x\n",cop_regs[0],cop_regs[1],cop_regs[2],cop_regs[3],cop_regs[4],cop_regs[5],cop_regs[6]);

	offs = (offset & 3) * 4;

	div = m_host_space->read_word(cop_regs[4] + offs);
	dir_offset = m_host_space->read_word(cop_regs[4] + offs + 8);
	//              offs_val = m_host_space.read_word(cop_regs[3] + offs);
	//420 / 180 = 500 : 400 = 30 / 50 = 98 / 18

	/* TODO: this probably trips a cop status flag */
	if (div == 0) { div = 1; }


	m_host_space->write_word((cop_regs[6] + offs + 4), ((m_host_space->read_word(cop_regs[5] + offs + 4) + dir_offset) / div));
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
1c - e38e ( 1c) (  38e) :  (984, ac4, d82, ac2, 39b, b9a, b9a, a9a)  5     b07f   (cupsoc, grainbow)
1c - e105 ( 1c) (  105) :  (a88, 994, 088, 000, 000, 000, 000, 000)  5     06fb   (zeroteam, xsedae)
*/
// controls GK position, aligned to the ball position
void raiden2cop_device::LEGACY_execute_e30e(int offset, uint16_t data)
{
	int dy = m_host_space->read_dword(cop_regs[2] + 4) - m_host_space->read_dword(cop_regs[0] + 4);
	int dx = m_host_space->read_dword(cop_regs[2] + 8) - m_host_space->read_dword(cop_regs[0] + 8);


	cop_status = 7;
	if (!dx)
	{
		cop_status |= 0x8000;
		cop_angle = 0;
	}
	else {
		cop_angle = (int)(atan(double(dy) / double(dx)) * 128.0 / M_PI);
		if (dx < 0)
			cop_angle += 0x80;

		cop_angle &= 0xff;
	}

#if LOG_Phytagoras
	printf("cmd %04x: dx = %d dy = %d angle = %02x %04x\n",data,dx,dy,cop_angle);
#endif

	// TODO: byte or word?
	if (data & 0x0080)
		cop_write_byte(cop_regs[0] + 0x34, cop_angle);
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
1d - eb8e ( 1d) (  38e) :  (984, ac4, d82, ac2, 39b, b9a, b9a, a9f)  5     b07f   (cupsoc, grainbow)
1d - ede5 ( 1d) (  5e5) :  (f88, a84, 986, 08a, 000, 000, 000, 000)  5     05f7   (zeroteam, xsedae)
*/

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
1e - f105 ( 1e) (  105) :  (a88, 994, 088, 000, 000, 000, 000, 000)  5     fefb   (cupsoc, grainbow)
1e - f205 ( 1e) (  205) :  (182, 2e0, 3c0, 0c0, 3c0, 000, 000, 000)  6     fff7   (raiden2, raidendx)
1e - f790 ( 1e) (  790) :  (f80, b84, b84, b84, b84, b84, b84, b84)  4     00ff   (zeroteam, xsedae)
*/

void raiden2cop_device::execute_f205(int offset, uint16_t data)
{
	m_host_space->write_dword(cop_regs[2], m_host_space->read_dword(cop_regs[0]+4));
}

/*
## - trig (up5) (low11) :  (sq0, sq1, sq2, sq3, sq4, sq5, sq6, sq7)  valu  mask
1f - fc84 ( 1f) (  484) :  (182, 280, 000, 000, 000, 000, 000, 000)  6     00ff   (zeroteam, xsedae)
*/


/*
[:raiden2cop] COPDIS: f105 s=f0 f1=0 l=3 f2=05 5 fefb f0 a88 15.0.08 [:raiden2cop] sub32 10(r0)
[:raiden2cop] COPDIS: f105 s=f0 f1=0 l=3 f2=05 5 fefb f1 994 13.0.14 [:raiden2cop] write16h 28(r0)
[:raiden2cop] COPDIS: f105 s=f0 f1=0 l=3 f2=05 5 fefb f2 088 01.0.08 [:raiden2cop] addmem32 10(r0)
*/
// seibu cup soccer, before cosine (ball dribbling actually?)
void raiden2cop_device::execute_f105(int offset, uint16_t data)
{
	// ...
}

#ifdef UNUSED_COMMANDS

// For reference only, will be nuked at some point

void raiden2cop_device::LEGACY_execute_130e(int offset, uint16_t data)
{
	int dy =  m_host_space->read_dword(cop_regs[1] + 4) - m_host_space->read_dword(cop_regs[0] + 4);
	int dx = m_host_space->read_dword(cop_regs[1] + 8) - m_host_space->read_dword(cop_regs[0] + 8);

	cop_status = 7;
	if (!dx) {
		cop_status |= 0x8000;
		cop_angle = 0;
	}
	else {
		cop_angle = (int)(atan(double(dy) / double(dx)) * 128.0 / M_PI);
		if (dx < 0)
			cop_angle += 0x80;
	}

	m_LEGACY_r0 = dy;
	m_LEGACY_r1 = dx;

	if (data & 0x80)
		m_host_space->write_word(cop_regs[0] + (0x34 ^ 2), cop_angle);
}

void raiden2cop_device::LEGACY_execute_3b30(int offset, uint16_t data)
{
	int dy = m_LEGACY_r0;
	int dx = m_LEGACY_r1;

	dx >>= 16;
	dy >>= 16;
	cop_dist = sqrt((double)(dx*dx + dy*dy));

	if (data & 0x80)
		m_host_space->write_word(cop_regs[0] + (0x38), cop_dist);
}

void raiden2cop_device::LEGACY_execute_42c2(int offset, uint16_t data)
{
	int dy = m_LEGACY_r0;
	int dx = m_LEGACY_r1;
	int div = m_host_space->read_word(cop_regs[0] + (0x36 ^ 2));
	int res;
	int cop_dist_raw;

	// divide by zero?
	if (!div)
	{
		// No emulation error here: heatbrl specifically tests this
		cop_status |= 0x8000;
		res = 0;
	}
	else
	{
		/* TODO: calculation of this one should occur at 0x3b30/0x3bb0 I *think* */
		/* TODO: recheck if cop_scale still masks at 3 with this command */
		dx >>= 11 + cop_scale;
		dy >>= 11 + cop_scale;
		cop_dist_raw = sqrt((double)(dx*dx + dy*dy));

		res = cop_dist_raw;
		res /= div;

		cop_dist = (1 << (5 - cop_scale)) / div;

		/* TODO: bits 5-6-15 */
		cop_status = 7;
	}

	m_host_space->write_word(cop_regs[0] + (0x38 ^ 2), res);
}

// used by seibu cup soccer, not sure if right so left out
void raiden2cop_device::execute_5105(int offset, uint16_t data)
{
	int res = m_host_space->read_dword(cop_regs[0]) +  m_host_space->read_dword(cop_regs[0]+8);
	m_host_space->write_dword(cop_regs[0]+4, res);
}

/*
[:raiden2cop] COPDIS: 5905 s=58 f1=0 l=3 f2=05 5 fffb 58 9c8 13.2.08 [:raiden2cop] write16h 10(r2)
[:raiden2cop] COPDIS: 5905 s=58 f1=0 l=3 f2=05 5 fffb 59 a84 15.0.04 [:raiden2cop] sub32 8(r0)
[:raiden2cop] COPDIS: 5905 s=58 f1=0 l=3 f2=05 5 fffb 5a 0a2 01.1.02 [:raiden2cop] addmem32 4(r1)
*/
void raiden2cop_device::execute_5905(int offset, uint16_t data)
{
	int res = m_host_space->read_dword(cop_regs[2]+10 + offset*4) - m_host_space->read_dword(cop_regs[0]+8 + offset*4);
	m_host_space->write_dword(cop_regs[1]+4 + offset *4, res);
}

#endif