// license:GPL-2.0+
// copyright-holders:byuu, Nach
/***************************************************************************
cx4ops.c
Code based on original work by zsKnight, anomie and Nach.
This implementation is based on C++ "cx4*.cpp" by byuu
(up to date with source v 0.49).
***************************************************************************/
//Sprite Functions
static void CX4_op00(running_machine& machine)
{
switch(cx4.reg[0x4d])
{
case 0x00: CX4_op00_00(machine); break;
case 0x03: CX4_op00_03(); break;
case 0x05: CX4_op00_05(machine); break;
case 0x07: CX4_op00_07(); break;
case 0x08: CX4_op00_08(machine); break;
case 0x0b: CX4_op00_0b(machine); break;
case 0x0c: CX4_op00_0c(machine); break;
}
}
//Draw Wireframe
static void CX4_op01(running_machine& machine)
{
memset(cx4.ram + 0x300, 0, 2304);
CX4_C4DrawWireFrame(machine);
}
//Propulsion
static void CX4_op05(running_machine &machine)
{
int32_t temp = 0x10000;
if(CX4_readw(0x1f83))
{
temp = CX4_sar((temp / CX4_readw(0x1f83)) * CX4_readw(0x1f81), 8);
}
CX4_writew(machine, 0x1f80, temp);
}
//Set Vector length
static void CX4_op0d(running_machine &machine)
{
cx4.C41FXVal = CX4_readw(0x1f80);
cx4.C41FYVal = CX4_readw(0x1f83);
cx4.C41FDistVal = CX4_readw(0x1f86);
cx4.tanval = sqrt(((double)cx4.C41FYVal) * ((double)cx4.C41FYVal) + ((double)cx4.C41FXVal) * ((double)cx4.C41FXVal));
cx4.tanval = (double)cx4.C41FDistVal / cx4.tanval;
cx4.C41FYVal = (int16_t)(((double)cx4.C41FYVal * cx4.tanval) * 0.99);
cx4.C41FXVal = (int16_t)(((double)cx4.C41FXVal * cx4.tanval) * 0.98);
CX4_writew(machine, 0x1f89, cx4.C41FXVal);
CX4_writew(machine, 0x1f8c, cx4.C41FYVal);
}
//Triangle
static void CX4_op10(void)
{
cx4.r0 = CX4_ldr(0);
cx4.r1 = CX4_ldr(1);
cx4.r4 = cx4.r0 & 0x1ff;
if(cx4.r1 & 0x8000)
{
cx4.r1 |= ~0x7fff;
}
CX4_mul(CX4_cos(cx4.r4), cx4.r1, &cx4.r5, &cx4.r2);
cx4.r5 = (cx4.r5 >> 16) & 0xff;
cx4.r2 = (cx4.r2 << 8) + cx4.r5;
CX4_mul(CX4_sin(cx4.r4), cx4.r1, &cx4.r5, &cx4.r3);
cx4.r5 = (cx4.r5 >> 16) & 0xff;
cx4.r3 = (cx4.r3 << 8) + cx4.r5;
CX4_str(0, cx4.r0);
CX4_str(1, cx4.r1);
CX4_str(2, cx4.r2);
CX4_str(3, cx4.r3);
CX4_str(4, cx4.r4);
CX4_str(5, cx4.r5);
}
//Triangle
static void CX4_op13(void)
{
cx4.r0 = CX4_ldr(0);
cx4.r1 = CX4_ldr(1);
cx4.r4 = cx4.r0 & 0x1ff;
CX4_mul(CX4_cos(cx4.r4), cx4.r1, &cx4.r5, &cx4.r2);
cx4.r5 = (cx4.r5 >> 8) & 0xffff;
cx4.r2 = (cx4.r2 << 16) + cx4.r5;
CX4_mul(CX4_sin(cx4.r4), cx4.r1, &cx4.r5, &cx4.r3);
cx4.r5 = (cx4.r5 >> 8) & 0xffff;
cx4.r3 = (cx4.r3 << 16) + cx4.r5;
CX4_str(0, cx4.r0);
CX4_str(1, cx4.r1);
CX4_str(2, cx4.r2);
CX4_str(3, cx4.r3);
CX4_str(4, cx4.r4);
CX4_str(5, cx4.r5);
}
//Pythagorean
static void CX4_op15(running_machine &machine)
{
double temp = 0.0;
cx4.C41FXVal = CX4_readw(0x1f80);
cx4.C41FYVal = CX4_readw(0x1f83);
temp = sqrt((double)cx4.C41FXVal * (double)cx4.C41FXVal + (double)cx4.C41FYVal * (double)cx4.C41FYVal);
cx4.C41FDist = (int16_t)temp;
CX4_writew(machine, 0x1f80, cx4.C41FDist);
}
//Calculate distance
static void CX4_op1f(running_machine &machine)
{
cx4.C41FXVal = CX4_readw(0x1f80);
cx4.C41FYVal = CX4_readw(0x1f83);
if(!cx4.C41FXVal)
{
cx4.C41FAngleRes = (cx4.C41FYVal > 0) ? 0x080 : 0x180;
}
else
{
cx4.tanval = ((double)cx4.C41FYVal) / ((double)cx4.C41FXVal);
cx4.C41FAngleRes = (int16_t)(atan(cx4.tanval) / (PI * 2) * 512);
cx4.C41FAngleRes = cx4.C41FAngleRes;
if(cx4.C41FXVal < 0)
{
cx4.C41FAngleRes += 0x100;
}
cx4.C41FAngleRes &= 0x1ff;
}
CX4_writew(machine, 0x1f86, cx4.C41FAngleRes);
}
//Trapezoid
static void CX4_op22(void)
{
int16_t angle1 = CX4_readw(0x1f8c) & 0x1ff;
int16_t angle2 = CX4_readw(0x1f8f) & 0x1ff;
int32_t tan1 = CX4_Tan(angle1);
int32_t tan2 = CX4_Tan(angle2);
int16_t y = CX4_readw(0x1f83) - CX4_readw(0x1f89);
int16_t left, right;
int32_t j;
for(j = 0; j < 225; j++, y++)
{
if(y >= 0)
{
left = CX4_sar((int32_t)tan1 * y, 16) - CX4_readw(0x1f80) + CX4_readw(0x1f86);
right = CX4_sar((int32_t)tan2 * y, 16) - CX4_readw(0x1f80) + CX4_readw(0x1f86) + CX4_readw(0x1f93);
if(left < 0 && right < 0)
{
left = 1;
right = 0;
}
else if(left < 0)
{
left = 0;
}
else if(right < 0)
{
right = 0;
}
if(left > 255 && right > 255)
{
left = 255;
right = 254;
}
else if(left > 255)
{
left = 255;
}
else if(right > 255)
{
right = 255;
}
}
else
{
left = 1;
right = 0;
}
cx4.ram[j + 0x800] = (uint8_t)left;
cx4.ram[j + 0x900] = (uint8_t)right;
}
}
//Multiply
static void CX4_op25(void)
{
cx4.r0 = CX4_ldr(0);
cx4.r1 = CX4_ldr(1);
CX4_mul(cx4.r0, cx4.r1, &cx4.r0, &cx4.r1);
CX4_str(0, cx4.r0);
CX4_str(1, cx4.r1);
}
//Transform Coords
static void CX4_op2d(running_machine &machine)
{
cx4.C4WFXVal = CX4_readw(0x1f81);
cx4.C4WFYVal = CX4_readw(0x1f84);
cx4.C4WFZVal = CX4_readw(0x1f87);
cx4.C4WFX2Val = CX4_read (0x1f89);
cx4.C4WFY2Val = CX4_read (0x1f8a);
cx4.C4WFDist = CX4_read (0x1f8b);
cx4.C4WFScale = CX4_readw(0x1f90);
CX4_C4TransfWireFrame2();
CX4_writew(machine, 0x1f80, cx4.C4WFXVal);
CX4_writew(machine, 0x1f83, cx4.C4WFYVal);
}
//Sum
static void CX4_op40(void)
{
uint32_t i;
cx4.r0 = 0;
for(i=0;i<0x800;i++)
{
cx4.r0 += cx4.ram[i];
}
CX4_str(0, cx4.r0);
}
//Square
static void CX4_op54(void)
{
cx4.r0 = CX4_ldr(0);
CX4_mul(cx4.r0, cx4.r0, &cx4.r1, &cx4.r2);
CX4_str(1, cx4.r1);
CX4_str(2, cx4.r2);
}
//Immediate Register
static void CX4_op5c(void)
{
CX4_str(0, 0x000000);
CX4_immediate_reg(0);
}
//Immediate Register (Multiple)
static void CX4_op5e(void) { CX4_immediate_reg( 0); }
static void CX4_op60(void) { CX4_immediate_reg( 3); }
static void CX4_op62(void) { CX4_immediate_reg( 6); }
static void CX4_op64(void) { CX4_immediate_reg( 9); }
static void CX4_op66(void) { CX4_immediate_reg(12); }
static void CX4_op68(void) { CX4_immediate_reg(15); }
static void CX4_op6a(void) { CX4_immediate_reg(18); }
static void CX4_op6c(void) { CX4_immediate_reg(21); }
static void CX4_op6e(void) { CX4_immediate_reg(24); }
static void CX4_op70(void) { CX4_immediate_reg(27); }
static void CX4_op72(void) { CX4_immediate_reg(30); }
static void CX4_op74(void) { CX4_immediate_reg(33); }
static void CX4_op76(void) { CX4_immediate_reg(36); }
static void CX4_op78(void) { CX4_immediate_reg(39); }
static void CX4_op7a(void) { CX4_immediate_reg(42); }
static void CX4_op7c(void) { CX4_immediate_reg(45); }
//Immediate ROM
static void CX4_op89(void)
{
CX4_str(0, 0x054336);
CX4_str(1, 0xffffff);
}