void draw_sprites()
{
int i;
int snum, sbit; // Sprite number/bit mask
int spr_coll = 0, gfx_coll = 0;
//// Clear sprite collision buffer
//{
// UInt32* lp = (UInt32*)spr_coll_buf_ptr - 1;
// for (i = 0; i < C64Display.DISPLAY_X / 4; i++)
// *++lp = 0;
//}
// Clear sprite collision buffer
for (int b = 0; b < spr_coll_buf.Length; b++)
{
spr_coll_buf[b] = 0;
}
// Loop for all sprites
for (snum = 0, sbit = 1; snum < 8; snum++, sbit <<= 1)
{
// Is sprite visible?
if ((spr_draw & sbit) != 0 && mx[snum] <= C64Display.DISPLAY_X - 32)
{
//byte* p = chunky_line_start + mx[snum] + 8;
int pIndex = _chunkyLineStartIndex + mx[snum] + 8;
//byte* q = (byte*)spr_coll_buf_ptr + mx[snum] + 8;
//int qIndex = spr_coll_buf_index + mx[snum] + 8;
int qIndex = mx[snum] + 8;
byte color = spr_color[snum];
// Fetch sprite data and mask
//UInt32 sdata = (UInt32)((spr_draw_data_ptr[snum * 4] << 24) |
// (spr_draw_data_ptr[snum * 4 + 1] << 16) |
// (spr_draw_data_ptr[snum * 4 + 2] << 8));
UInt32 sdata = (UInt32)((spr_draw_data[snum * 4] << 24) |
(spr_draw_data[snum * 4 + 1] << 16) |
(spr_draw_data[snum * 4 + 2] << 8));
int spr_mask_pos = mx[snum] + 8; // Sprite bit position in fore_mask_buf
//byte* fmbp = fore_mask_buf_ptr + (spr_mask_pos / 8);
int fmbpIndex = 0 + (spr_mask_pos / 8);
//if (fmbpIndex == 0)
//{
// Debug.WriteLine("fmbpIndex == 0");
//}
int sshift = spr_mask_pos & 7;
//UInt32 fore_mask = (UInt32)((((*(fmbp + 0) << 24) | (*(fmbp + 1) << 16) | (*(fmbp + 2) << 8)
// | (*(fmbp + 3))) << sshift) | (*(fmbp + 4) >> (8 - sshift)));
UInt32 fore_mask = (UInt32)(((
(fore_mask_buf[(fmbpIndex + 0)] << 24) |
(fore_mask_buf[(fmbpIndex + 1)] << 16) |
(fore_mask_buf[(fmbpIndex + 2)] << 8) |
(fore_mask_buf[(fmbpIndex + 3)])) << sshift) |
(fore_mask_buf[(fmbpIndex + 4)] >> (8 - sshift)
));
if ((mxe & sbit) != 0)
{ // X-expanded
if (mx[snum] > C64Display.DISPLAY_X - 56)
continue;
UInt32 sdata_l = 0, sdata_r = 0, fore_mask_r;
//fore_mask_r = (UInt32)((((*(fmbp + 4) << 24) | (*(fmbp + 5) << 16) | (*(fmbp + 6) << 8)
// | (*(fmbp + 7))) << sshift) | (*(fmbp + 8) >> (8 - sshift)));
fore_mask_r = (UInt32)(((
(fore_mask_buf[(fmbpIndex + 4)] << 24) |
(fore_mask_buf[(fmbpIndex + 5)] << 16) |
(fore_mask_buf[(fmbpIndex + 6)] << 8) |
(fore_mask_buf[(fmbpIndex + 7)])) << sshift) |
(fore_mask_buf[(fmbpIndex + 8)] >> (8 - sshift)
));
if ((mmc & sbit) != 0)
{ // Multicolor mode
UInt32 plane0_l, plane0_r, plane1_l, plane1_r;
// Expand sprite data
//sdata_l = (UInt32)(MultiExpTable_ptr[sdata >> 24 & 0xff] << 16 | MultiExpTable_ptr[sdata >> 16 & 0xff]);
//sdata_r = (UInt32)(MultiExpTable_ptr[sdata >> 8 & 0xff] << 16);
sdata_l = (UInt32)(MultiExpTable[sdata >> 24 & 0xff] << 16 | MultiExpTable[sdata >> 16 & 0xff]);
sdata_r = (UInt32)(MultiExpTable[sdata >> 8 & 0xff] << 16);
// Convert sprite chunky pixels to bitplanes
plane0_l = (sdata_l & 0x55555555) | (sdata_l & 0x55555555) << 1;
plane1_l = (sdata_l & 0xaaaaaaaa) | (sdata_l & 0xaaaaaaaa) >> 1;
plane0_r = (sdata_r & 0x55555555) | (sdata_r & 0x55555555) << 1;
plane1_r = (sdata_r & 0xaaaaaaaa) | (sdata_r & 0xaaaaaaaa) >> 1;
// Collision with graphics?
if ((fore_mask & (plane0_l | plane1_l)) != 0 || (fore_mask_r & (plane0_r | plane1_r)) != 0)
{
gfx_coll |= sbit;
if ((mdp & sbit) != 0)
{
plane0_l &= ~fore_mask; // Mask sprite if in background
plane1_l &= ~fore_mask;
plane0_r &= ~fore_mask_r;
plane1_r &= ~fore_mask_r;
}
}
// Paint sprite
for (i = 0; i < 32; i++, plane0_l <<= 1, plane1_l <<= 1)
{
byte col;
if ((plane1_l & 0x80000000) != 0)
{
if ((plane0_l & 0x80000000) != 0)
col = mm1_color;
else
col = color;
}
else
{
if ((plane0_l & 0x80000000) != 0)
col = mm0_color;
else
continue;
}
//if (q[i] != 0)
// spr_coll |= q[i] | sbit;
//else
//{
// p[i] = col;
// q[i] = (byte)sbit;
//}
if (spr_coll_buf[qIndex + i] != 0)
spr_coll |= spr_coll_buf[qIndex + i] | sbit;
else
{
_display.SetPixel(pIndex + i, col);
spr_coll_buf[qIndex + i] = (byte)sbit;
}
}
for (; i < 48; i++, plane0_r <<= 1, plane1_r <<= 1)
{
byte col;
if ((plane1_r & 0x80000000) != 0)
{
if ((plane0_r & 0x80000000) != 0)
col = mm1_color;
else
col = color;
}
else
{
if ((plane0_r & 0x80000000) != 0)
col = mm0_color;
else
continue;
}
//if (q[_chunkyLineStartIndex + i] != 0)
// spr_coll |= q[_chunkyLineStartIndex + i] | sbit;
//else
//{
// p[i] = col;
// q[i] = (byte)sbit;
//}
if (spr_coll_buf[qIndex + i] != 0)
spr_coll |= spr_coll_buf[qIndex + i] | sbit;
else
{
_display.SetPixel(pIndex + i, col);
spr_coll_buf[qIndex + i] = (byte)sbit;
}
}
}
else
{ // Standard mode
// Expand sprite data
//sdata_l = (UInt32)(ExpTable_ptr[sdata >> 24 & 0xff] << 16 | ExpTable_ptr[sdata >> 16 & 0xff]);
//sdata_r = (UInt32)(ExpTable_ptr[sdata >> 8 & 0xff] << 16);
sdata_l = (UInt32)(ExpTable[ExpTable_index + (sdata >> 24 & 0xff)] << 16 |
ExpTable[ExpTable_index + (sdata >> 16 & 0xff)]);
sdata_r = (UInt32)(ExpTable[ExpTable_index + (sdata >> 8 & 0xff)] << 16);
// Collision with graphics?
if ((fore_mask & sdata_l) != 0 || (fore_mask_r & sdata_r) != 0)
{
gfx_coll |= sbit;
if ((mdp & sbit) != 0)
{
sdata_l &= ~fore_mask; // Mask sprite if in background
sdata_r &= ~fore_mask_r;
}
}
// Paint sprite
//for (i = 0; i < 32; i++, sdata_l <<= 1)
// if ((sdata_l & 0x80000000) != 0)
// {
// if (q[i] != 0) // Collision with sprite?
// spr_coll |= q[i] | sbit;
// else
// { // Draw pixel if no collision
// p[i] = color;
// q[i] = (byte)sbit;
// }
// }
//for (; i < 48; i++, sdata_r <<= 1)
// if ((sdata_r & 0x80000000) != 0)
// {
// if (q[i] != 0) // Collision with sprite?
// spr_coll |= q[i] | sbit;
// else
// { // Draw pixel if no collision
// p[i] = color;
// q[i] = (byte)sbit;
// }
// }
for (i = 0; i < 32; i++, sdata_l <<= 1)
if ((sdata_l & 0x80000000) != 0)
{
if (spr_coll_buf[qIndex + i] != 0) // Collision with sprite?
spr_coll |= spr_coll_buf[qIndex + i] | sbit;
else
{ // Draw pixel if no collision
_display.SetPixel(pIndex + i, color);
spr_coll_buf[qIndex + i] = (byte)sbit;
}
}
for (; i < 48; i++, sdata_r <<= 1)
if ((sdata_r & 0x80000000) != 0)
{
if (spr_coll_buf[qIndex + i] != 0) // Collision with sprite?
spr_coll |= spr_coll_buf[qIndex + i] | sbit;
else
{ // Draw pixel if no collision
_display.SetPixel(pIndex + i, color);
spr_coll_buf[qIndex + i] = (byte)sbit;
}
}
}
}
else
{ // Unexpanded
if ((mmc & sbit) != 0)
{ // Multicolor mode
UInt32 plane0, plane1;
// Convert sprite chunky pixels to bitplanes
plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1;
plane1 = (sdata & 0xaaaaaaaa) | (sdata & 0xaaaaaaaa) >> 1;
// Collision with graphics?
if ((fore_mask & (plane0 | plane1)) != 0)
{
gfx_coll |= sbit;
if ((mdp & sbit) != 0)
{
plane0 &= ~fore_mask; // Mask sprite if in background
plane1 &= ~fore_mask;
}
}
// Paint sprite
for (i = 0; i < 24; i++, plane0 <<= 1, plane1 <<= 1)
{
byte col;
if ((plane1 & 0x80000000) != 0)
{
if ((plane0 & 0x80000000) != 0)
col = mm1_color;
else
col = color;
}
else
{
if ((plane0 & 0x80000000) != 0)
col = mm0_color;
else
continue;
}
//if (q[i] != 0)
// spr_coll |= q[i] | sbit;
//else
//{
// p[i] = col;
// q[i] = (byte)sbit;
//}
if (spr_coll_buf[qIndex + i] != 0)
spr_coll |= spr_coll_buf[qIndex + i] | sbit;
else
{
_display.SetPixel(pIndex + i, col);
spr_coll_buf[qIndex + i] = (byte)sbit;
}
}
}
else
{ // Standard mode
// Collision with graphics?
if ((fore_mask & sdata) != 0)
{
gfx_coll |= sbit;
if ((mdp & sbit) != 0)
sdata &= ~fore_mask; // Mask sprite if in background
}
// Paint sprite
for (i = 0; i < 24; i++, sdata <<= 1)
if ((sdata & 0x80000000) != 0)
{
//if (q[i] != 0)
//{ // Collision with sprite?
// spr_coll |= q[i] | sbit;
//}
//else
//{ // Draw pixel if no collision
// p[i] = color;
// q[i] = (byte)sbit;
//}
if (spr_coll_buf[qIndex + i] != 0)
{ // Collision with sprite?
spr_coll |= spr_coll_buf[qIndex + i] | sbit;
}
else
{ // Draw pixel if no collision
_display.SetPixel(pIndex + i, color);
spr_coll_buf[qIndex + i] = (byte)sbit;
}
}
}
}
}
}
if (GlobalPrefs.ThePrefs.SpriteCollisions)
{
// Check sprite-sprite collisions
if (clx_spr != 0)
clx_spr |= (byte)spr_coll;
else
{
clx_spr |= (byte)spr_coll;
irq_flag |= 0x04;
if ((irq_mask & 0x04) != 0)
{
irq_flag |= 0x80;
_cpu.TriggerVICIRQ();
}
}
// Check sprite-background collisions
if (clx_bgr != 0)
clx_bgr |= (byte)gfx_coll;
else
{
clx_bgr |= (byte)gfx_coll;
irq_flag |= 0x02;
if ((irq_mask & 0x02) != 0)
{
irq_flag |= 0x80;
_cpu.TriggerVICIRQ();
}
}
}
}