private bool readPacket(ref CdgPacket pack) { if (m_pStream == null || m_pStream.eof() == 1) { return(false); } int read = 0; read += m_pStream.read(ref pack.command, 1); read += m_pStream.read(ref pack.instruction, 1); read += m_pStream.read(ref pack.parityQ, 2); read += m_pStream.read(ref pack.data, 16); read += m_pStream.read(ref pack.parityP, 4); return(read == 24); }
public bool renderAtPosition(long ms) { CdgPacket pack = new CdgPacket(); long numPacks = 0; bool res = true; if ((m_pStream == null)) { return(false); } if ((ms < m_positionMs)) { if ((m_pStream.seek(0, SeekOrigin.Begin) < 0)) { return(false); } m_positionMs = 0; } //duration of one packet is 1/300 seconds (4 packets per sector, 75 sectors per second) numPacks = ms - m_positionMs; numPacks /= 10; m_positionMs += numPacks * 10; numPacks *= 3; //TODO: double check logic due to inline while loop fucntionality //AndAlso m_pSurface.rgbData Is Nothing while (numPacks > 0) { res = readPacket(ref pack); processPacket(ref pack); numPacks -= 1; } render(); return(res); }
private void borderPreset(ref CdgPacket pack) { int colour = 0; int ri = 0; int ci = 0; colour = pack.data[0] & 0xf; m_borderColourIndex = colour; //The border area is the area contained with a rectangle //defined by (0,0,300,216) minus the interior pixels which are contained //within a rectangle defined by (6,12,294,204). for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++) { for (ci = 0; ci <= 5; ci++) { m_pixelColours[ri, ci] = Convert.ToByte(colour); } for (ci = CDG_FULL_WIDTH - 6; ci <= CDG_FULL_WIDTH - 1; ci++) { m_pixelColours[ri, ci] = Convert.ToByte(colour); } } for (ci = 6; ci <= CDG_FULL_WIDTH - 7; ci++) { for (ri = 0; ri <= 11; ri++) { m_pixelColours[ri, ci] = Convert.ToByte(colour); } for (ri = CDG_FULL_HEIGHT - 12; ri <= CDG_FULL_HEIGHT - 1; ri++) { m_pixelColours[ri, ci] = Convert.ToByte(colour); } } }
private void memoryPreset(ref CdgPacket pack) { int colour = 0; int ri = 0; int ci = 0; int repeat = 0; colour = pack.data[0] & 0xf; repeat = pack.data[1] & 0xf; //Our new interpretation of CD+G Revealed is that memory preset //commands should also change the border m_presetColourIndex = colour; m_borderColourIndex = colour; //we have a reliable data stream, so the repeat command //is executed only the first time if ((repeat == 0)) { //Note that this may be done before any load colour table //commands by some CDGs. So the load colour table itself //actual recalculates the RGB values for all pixels when //the colour table changes. //Set the preset colour for every pixel. Must be stored in //the pixel colour table indeces array for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++) { for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++) { m_pixelColours[ri, ci] = Convert.ToByte(colour); } } } }
private void loadColorTable(ref CdgPacket pack, int table) { for (int i = 0; i <= 7; i++) { //[---high byte---] [---low byte----] //7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 //X X r r r r g g X X g g b b b b byte byte0 = pack.data[2 * i]; byte byte1 = pack.data[2 * i + 1]; int red = (byte0 & 0x3f) >> 2; int green = ((byte0 & 0x3) << 2) | ((byte1 & 0x3f) >> 4); int blue = byte1 & 0xf; red *= 17; green *= 17; blue *= 17; if (m_pSurface != null) { m_colourTable[i + table * 8] = m_pSurface.MapRGBColour(red, green, blue); } } }
private void scroll(ref CdgPacket pack, bool copy) { int colour = 0; int hScroll = 0; int vScroll = 0; int hSCmd = 0; int hOffset = 0; int vSCmd = 0; int vOffset = 0; int vScrollPixels = 0; int hScrollPixels = 0; //Decode the scroll command parameters colour = pack.data[0] & 0xf; hScroll = pack.data[1] & 0x3f; vScroll = pack.data[2] & 0x3f; hSCmd = (hScroll & 0x30) >> 4; hOffset = (hScroll & 0x7); vSCmd = (vScroll & 0x30) >> 4; vOffset = (vScroll & 0xf); m_hOffset = hOffset < 5 ? hOffset : 5; m_vOffset = vOffset < 11 ? vOffset : 11; //Scroll Vertical - Calculate number of pixels vScrollPixels = 0; if ((vSCmd == 2)) { vScrollPixels = -12; } else if ((vSCmd == 1)) { vScrollPixels = 12; } //Scroll Horizontal- Calculate number of pixels hScrollPixels = 0; if ((hSCmd == 2)) { hScrollPixels = -6; } else if ((hSCmd == 1)) { hScrollPixels = 6; } if ((hScrollPixels == 0 && vScrollPixels == 0)) { return; } //Perform the actual scroll. byte[,] temp = new byte[CDG_FULL_HEIGHT + 1, CDG_FULL_WIDTH + 1]; int vInc = vScrollPixels + CDG_FULL_HEIGHT; int hInc = hScrollPixels + CDG_FULL_WIDTH; int ri = 0; //row index int ci = 0; //column index for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++) { for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++) { temp[(ri + vInc) % CDG_FULL_HEIGHT, (ci + hInc) % CDG_FULL_WIDTH] = m_pixelColours[ri, ci]; } } //if copy is false, we were supposed to fill in the new pixels //with a new colour. Go back and do that now. if ((copy == false)) { if ((vScrollPixels > 0)) { for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++) { for (ri = 0; ri <= vScrollPixels - 1; ri++) { temp[ri, ci] = Convert.ToByte(colour); } } } else if ((vScrollPixels < 0)) { for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++) { for (ri = CDG_FULL_HEIGHT + vScrollPixels; ri <= CDG_FULL_HEIGHT - 1; ri++) { temp[ri, ci] = Convert.ToByte(colour); } } } if ((hScrollPixels > 0)) { for (ci = 0; ci <= hScrollPixels - 1; ci++) { for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++) { temp[ri, ci] = Convert.ToByte(colour); } } } else if ((hScrollPixels < 0)) { for (ci = CDG_FULL_WIDTH + hScrollPixels; ci <= CDG_FULL_WIDTH - 1; ci++) { for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++) { temp[ri, ci] = Convert.ToByte(colour); } } } } //Now copy the temporary buffer back to our array for (ri = 0; ri <= CDG_FULL_HEIGHT - 1; ri++) { for (ci = 0; ci <= CDG_FULL_WIDTH - 1; ci++) { m_pixelColours[ri, ci] = temp[ri, ci]; } } }
private void defineTransparentColour(ref CdgPacket pack) { m_transparentColour = pack.data[0] & 0xf; }
private void tileBlock(ref CdgPacket pack, bool bXor) { int colour0 = 0; int colour1 = 0; int column_index = 0; int row_index = 0; int myByte = 0; int pixel = 0; int xor_col = 0; int currentColourIndex = 0; int new_col = 0; colour0 = pack.data[0] & 0xf; colour1 = pack.data[1] & 0xf; row_index = ((pack.data[2] & 0x1f) * 12); column_index = ((pack.data[3] & 0x3f) * 6); if ((row_index > (CDG_FULL_HEIGHT - TILE_HEIGHT))) { return; } if ((column_index > (CDG_FULL_WIDTH - TILE_WIDTH))) { return; } //Set the pixel array for each of the pixels in the 12x6 tile. //Normal = Set the colour to either colour0 or colour1 depending //on whether the pixel value is 0 or 1. //XOR = XOR the colour with the colour index currently there. for (int i = 0; i <= 11; i++) { myByte = (pack.data[4 + i] & 0x3f); for (int j = 0; j <= 5; j++) { pixel = (myByte >> (5 - j)) & 0x1; if ((bXor)) { //Tile Block XOR if ((pixel == 0)) { xor_col = colour0; } else { xor_col = colour1; } //Get the colour index currently at this location, and xor with it currentColourIndex = m_pixelColours[row_index + i, column_index + j]; new_col = currentColourIndex ^ xor_col; } else { if ((pixel == 0)) { new_col = colour0; } else { new_col = colour1; } } //Set the pixel with the new colour. We set both the surfarray //containing actual RGB values, as well as our array containing //the colour indexes into our colour table. m_pixelColours[row_index + i, column_index + j] = Convert.ToByte(new_col); } } }
private void processPacket(ref CdgPacket pack) { int inst_code = 0; if (((pack.command[0] & CDG_MASK) == CDG_COMMAND)) { inst_code = (pack.instruction[0] & CDG_MASK); switch (inst_code) { case CDG_INST_MEMORY_PRESET: memoryPreset(ref pack); return; case CDG_INST_BORDER_PRESET: borderPreset(ref pack); return; case CDG_INST_TILE_BLOCK: tileBlock(ref pack, false); return; case CDG_INST_SCROLL_PRESET: scroll(ref pack, false); return; case CDG_INST_SCROLL_COPY: scroll(ref pack, true); return; case CDG_INST_DEF_TRANSP_COL: defineTransparentColour(ref pack); return; case CDG_INST_LOAD_COL_TBL_LO: loadColorTable(ref pack, 0); return; case CDG_INST_LOAD_COL_TBL_HIGH: loadColorTable(ref pack, 1); return; case CDG_INST_TILE_BLOCK_XOR: tileBlock(ref pack, true); return; default: //Ignore the unsupported commands return; } } }