mirror of
https://github.com/Team-Resurgent/XBMC4Xbox.git
synced 2026-08-15 11:18:13 -07:00
If ever adding the XBMC4Xbox source to GitHub use "git add -f -A" or it wont add all the files.
316 lines
8.6 KiB
C++
316 lines
8.6 KiB
C++
/*
|
|
* Copyright (C) 2005-2013 Team XBMC
|
|
* http://xbmc.org
|
|
*
|
|
* This Program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This Program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with XBMC; see the file COPYING. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "system.h"
|
|
#include "Cdg.h"
|
|
|
|
CCdg::CCdg()
|
|
{
|
|
m_hOffset = NULL;
|
|
m_vOffset = NULL;
|
|
m_BgroundColor = 0xFF;
|
|
m_BorderColor = 0xFF;
|
|
memset( (void *) &m_SubCode, 0, sizeof(SubCode));
|
|
ClearDisplay();
|
|
}
|
|
CCdg::~CCdg()
|
|
{}
|
|
|
|
void CCdg::ReadSubCode(SubCode* pPacket)
|
|
{
|
|
m_SubCode = *pPacket;
|
|
if ((m_SubCode.command & SC_MASK) == SC_CDG_COMMAND) // CD+G?
|
|
{
|
|
switch (m_SubCode.instruction & SC_MASK)
|
|
{
|
|
case CDG_TILEBLOCKNORMAL: TileBlock(FALSE); break;
|
|
case CDG_TILEBLOCKXOR: TileBlock(TRUE); break;
|
|
case CDG_SCROLLPRESET: Scroll(FALSE); break;
|
|
case CDG_SCROLLCOPY: Scroll(TRUE); break;
|
|
case CDG_MEMORYPRESET: MemoryPreset(); break;
|
|
case CDG_BORDERPRESET: BorderPreset(); break;
|
|
case CDG_ALPHA: SetAlpha(); break;
|
|
case CDG_COLORTABLELO: ColorTable(TRUE); break;
|
|
case CDG_COLORTABLEHI: ColorTable(FALSE); break;
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
CDG_COLOR CCdg::GetColor(BYTE ClutOffset)
|
|
{
|
|
if (ClutOffset & 0xF0) return 0;
|
|
return m_ColorTable[ClutOffset];
|
|
}
|
|
|
|
BYTE CCdg::GetClutOffset(UINT uiRow, UINT uiCol)
|
|
{
|
|
if (uiRow >= HEIGHT || uiCol >= WIDTH)
|
|
return m_BorderColor;
|
|
return m_PixelMap[uiRow][uiCol];
|
|
}
|
|
|
|
UINT CCdg::GetHOffset()
|
|
{
|
|
return m_hOffset;
|
|
}
|
|
|
|
UINT CCdg::GetVOffset()
|
|
{
|
|
return m_vOffset;
|
|
}
|
|
|
|
void CCdg::ClearDisplay()
|
|
{
|
|
memset( (void *) m_PixelMap, 0, HEIGHT*WIDTH*sizeof(BYTE));
|
|
memset((void*) m_ColorTable, 0, 16*sizeof(CDG_COLOR));
|
|
}
|
|
BYTE CCdg::GetBackgroundColor()
|
|
{
|
|
return m_BgroundColor;
|
|
}
|
|
|
|
BYTE CCdg::GetBorderColor()
|
|
{
|
|
return m_BorderColor;
|
|
}
|
|
|
|
void CCdg::MemoryPreset()
|
|
{
|
|
CDG_MemPreset* preset = (CDG_MemPreset*) & (m_SubCode.data);
|
|
BYTE Repeat = preset->repeat & 0x0F;
|
|
if (Repeat) return ; //No need for multiple clearings, we have a reliable stream...
|
|
m_BgroundColor = preset->color & 0x0F;
|
|
UINT i, j;
|
|
for (i = BORDERWIDTH ; i < WIDTH - BORDERWIDTH ; i++)
|
|
for (j = BORDERHEIGHT ; j < HEIGHT - BORDERHEIGHT ; j++)
|
|
m_PixelMap[j][i] = m_BgroundColor;
|
|
}
|
|
|
|
void CCdg::BorderPreset()
|
|
{
|
|
CDG_BorderPreset* preset = ( CDG_BorderPreset*) & (m_SubCode.data);
|
|
m_BorderColor = preset->color & 0x0F;
|
|
UINT i, j;
|
|
for (i = 0 ;i < BORDERWIDTH;i++)
|
|
for (j = 0;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = m_BorderColor;
|
|
for (i = WIDTH - BORDERWIDTH ;i < WIDTH;i++)
|
|
for (j = 0;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = m_BorderColor;
|
|
for (i = 0 ;i < WIDTH;i++)
|
|
for (j = 0;j < BORDERHEIGHT;j++)
|
|
m_PixelMap[j][i] = m_BorderColor;
|
|
for (i = 0 ;i < WIDTH;i++)
|
|
for (j = HEIGHT - BORDERHEIGHT;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = m_BorderColor;
|
|
}
|
|
|
|
void CCdg::ColorTable(bool IsLo)
|
|
{
|
|
UINT offset;
|
|
if (IsLo) offset = 0;
|
|
else offset = 8;
|
|
CDG_LoadCLUT* clut = (CDG_LoadCLUT*) & (m_SubCode.data);
|
|
CDG_COLOR red, green, greentemp, blue;
|
|
for (UINT i = 0; i < 8; i++)
|
|
{
|
|
red = clut->colorSpec[i] & 0x003C;
|
|
red = red << 6;
|
|
greentemp = (clut->colorSpec[i] & 0x3000) >> 8;
|
|
green = (clut->colorSpec[i] & 0x0003) << 6;
|
|
green |= greentemp;
|
|
blue = (clut->colorSpec[i] & 0x0F00) >> 8;
|
|
m_ColorTable[offset + i] = 0xF000 | red | green | blue; //Defaults to opaque alpha
|
|
}
|
|
}
|
|
|
|
void CCdg::Scroll(bool IsLoop)
|
|
{
|
|
CDG_Scroll * scroll = (CDG_Scroll*) & (m_SubCode.data);
|
|
scroll->color &= 0x0F;
|
|
BYTE* pcolor;
|
|
if (IsLoop) pcolor = NULL; // Is looping mode
|
|
else pcolor = (BYTE*) & scroll->color;
|
|
BYTE hSCmd = (scroll->hScroll & 0x30) >> 4;
|
|
BYTE vSCmd = (scroll->vScroll & 0x30) >> 4;
|
|
|
|
switch (hSCmd)
|
|
{
|
|
case 1: ScrollRight(pcolor); break;
|
|
case 2: ScrollLeft(pcolor); break;
|
|
default: break;
|
|
}
|
|
switch (vSCmd)
|
|
{
|
|
case 1: ScrollDown(pcolor); break;
|
|
case 2: ScrollUp(pcolor); break;
|
|
default: break;
|
|
}
|
|
m_hOffset = scroll->hScroll & 0x07;
|
|
m_vOffset = scroll->vScroll & 0x0F;
|
|
}
|
|
|
|
void CCdg::ScrollRight(BYTE* pcolor)
|
|
{
|
|
BYTE PixelTemp[HEIGHT][BORDERWIDTH];
|
|
UINT i, j;
|
|
if (!pcolor) //Loop the scrolling
|
|
{
|
|
for (i = WIDTH - BORDERWIDTH ; i < WIDTH ; i++)
|
|
for (j = 0;j < HEIGHT;j++)
|
|
PixelTemp[j][BORDERWIDTH - WIDTH + i] = m_PixelMap[j][i];
|
|
}
|
|
else //Fill the background
|
|
{
|
|
for (i = WIDTH - BORDERWIDTH;i < WIDTH;i++)
|
|
for (j = 0;j < HEIGHT;j++)
|
|
PixelTemp[j][BORDERWIDTH - WIDTH + i] = *pcolor;
|
|
}
|
|
for (i = BORDERWIDTH ; i < WIDTH ; i++) //Fill scrolled area
|
|
for (j = 0;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = m_PixelMap[j][i - BORDERWIDTH];
|
|
for (i = 0;i < BORDERWIDTH;i++) //Fill uncovered area
|
|
for (j = 0;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = PixelTemp[j][i];
|
|
}
|
|
|
|
void CCdg::ScrollLeft(BYTE* pcolor)
|
|
{
|
|
BYTE PixelTemp[HEIGHT][BORDERWIDTH];
|
|
UINT i, j;
|
|
if (!pcolor) //Loop the scrolling
|
|
{
|
|
for (i = 0;i < BORDERWIDTH;i++)
|
|
for (j = 0;j < HEIGHT;j++)
|
|
PixelTemp[j][i] = m_PixelMap[j][i];
|
|
}
|
|
else //Fill the background
|
|
{
|
|
for (i = 0;i < BORDERWIDTH;i++)
|
|
for (j = 0;j < HEIGHT;j++)
|
|
PixelTemp[j][i] = *pcolor;
|
|
}
|
|
for (i = 0;i < WIDTH - BORDERWIDTH;i++) //Fill scrolled area
|
|
for (j = 0;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = m_PixelMap[j][i + BORDERWIDTH];
|
|
for (i = WIDTH - BORDERWIDTH;i < WIDTH;i++) //Fill uncovered area
|
|
for (j = 0;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = PixelTemp[j][i + BORDERWIDTH - WIDTH];
|
|
}
|
|
|
|
void CCdg::ScrollUp(BYTE* pcolor)
|
|
{
|
|
BYTE PixelTemp[BORDERHEIGHT][WIDTH];
|
|
UINT i, j;
|
|
if (!pcolor) //Loop the scrolling
|
|
{
|
|
for (i = 0;i < WIDTH;i++)
|
|
for (j = 0 ; j < BORDERHEIGHT ;j++)
|
|
PixelTemp[j][i] = m_PixelMap[j][i];
|
|
}
|
|
else //Fill with background
|
|
{
|
|
for (i = 0;i < WIDTH;i++)
|
|
for (j = 0;j < BORDERHEIGHT;j++)
|
|
PixelTemp[j][i] = *pcolor;
|
|
}
|
|
for (i = 0;i < WIDTH;i++) //Fill scrolled area
|
|
for (j = 0;j < HEIGHT - BORDERHEIGHT;j++)
|
|
m_PixelMap[j][i] = m_PixelMap[j + BORDERHEIGHT][i];
|
|
for (i = 0;i < WIDTH;i++) //Fill uncovered area
|
|
for (j = HEIGHT - BORDERHEIGHT;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = PixelTemp[BORDERHEIGHT - HEIGHT + j][i];
|
|
}
|
|
|
|
void CCdg::ScrollDown(BYTE* pcolor)
|
|
{
|
|
BYTE PixelTemp[BORDERHEIGHT][WIDTH];
|
|
UINT i, j;
|
|
if (!pcolor) //Loop the scrolling
|
|
{
|
|
for (i = 0;i < WIDTH;i++)
|
|
for (j = HEIGHT - BORDERHEIGHT;j < HEIGHT;j++)
|
|
PixelTemp[BORDERHEIGHT - HEIGHT + j][i] = m_PixelMap[j][i];
|
|
}
|
|
else //Fill with background
|
|
{
|
|
for (i = 0;i < WIDTH;i++)
|
|
for (j = HEIGHT - BORDERHEIGHT;j < HEIGHT;j++)
|
|
PixelTemp[BORDERHEIGHT - HEIGHT + j][i] = *pcolor;
|
|
}
|
|
for (i = 0;i < WIDTH;i++) //Fill scrolled area
|
|
for (j = BORDERHEIGHT;j < HEIGHT;j++)
|
|
m_PixelMap[j][i] = m_PixelMap[j - BORDERHEIGHT][i];
|
|
for (i = 0;i < WIDTH;i++) //Fill uncovered area
|
|
for (j = 0;j < BORDERHEIGHT;j++)
|
|
m_PixelMap[j][i] = PixelTemp[j][i];
|
|
}
|
|
|
|
void CCdg::SetAlpha()
|
|
{
|
|
BYTE AlphaColor = ((BYTE) (*m_SubCode.data)) & 0x0F;
|
|
m_ColorTable[AlphaColor] &= 0x0FFF;
|
|
}
|
|
|
|
|
|
void CCdg::TileBlock(bool IsXor)
|
|
{
|
|
CDG_Tile* tile = (CDG_Tile*) & (m_SubCode.data);
|
|
BYTE color_0 = tile->color0 & 0x0F;
|
|
BYTE color_1 = tile->color1 & 0x0F;
|
|
UINT row_offset = (tile->row & 0x1F) * 12;
|
|
UINT col_offset = (tile->column & 0x3F) * 6;
|
|
if (row_offset > HEIGHT - BORDERHEIGHT || col_offset > WIDTH - BORDERWIDTH)
|
|
return ;
|
|
BYTE bTemp;
|
|
BYTE mask[6] = {0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
|
|
|
switch (IsXor)
|
|
{
|
|
case TRUE:
|
|
for (int i = 0;i < 12;i++)
|
|
{
|
|
bTemp = tile->tilePixels[i] & 0x3F;
|
|
for (int j = 0; j < 6;j++)
|
|
{
|
|
if (bTemp & mask[j]) //pixel xored with color1
|
|
m_PixelMap[row_offset + i][col_offset + j] ^= color_1;
|
|
else //pixel xored with color0
|
|
m_PixelMap[row_offset + i][col_offset + j] ^= color_0;
|
|
}
|
|
}
|
|
break;
|
|
case FALSE:
|
|
for (int i = 0;i < 12;i++)
|
|
{
|
|
bTemp = tile->tilePixels[i] & 0x3F;
|
|
for (int j = 0; j < 6;j++)
|
|
{
|
|
if (bTemp & mask[j]) //pixel set to color1
|
|
m_PixelMap[row_offset + i][col_offset + j] = color_1;
|
|
else //pixel set to color0
|
|
m_PixelMap[row_offset + i][col_offset + j] = color_0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|