void CVPU1::Cmd_DIRECT(StreamType& stream, CODE nCommand) { uint32 nSize = stream.GetAvailableReadBytes(); nSize = std::min<uint32>(m_CODE.nIMM * 0x10, nSize); assert((nSize & 0x0F) == 0); if(nSize != 0) { uint8* packet = reinterpret_cast<uint8*>(alloca(nSize)); stream.Read(packet, nSize); int32 remainingLength = nSize; while(remainingLength > 0) { uint32 processed = m_vif.GetGif().ProcessPacket(packet, 0, remainingLength, CGsPacketMetadata(2)); packet += processed; remainingLength -= processed; assert(remainingLength >= 0); } } m_CODE.nIMM -= (nSize / 0x10); if((m_CODE.nIMM == 0) && (nSize != 0)) { m_STAT.nVPS = 0; } else { m_STAT.nVPS = 1; } }
bool CVPU::Unpack_V32(StreamType& stream, uint128& result, unsigned int fields) { if(stream.GetAvailableReadBytes() < (fields * 4)) return false; stream.Read(&result, (fields * 4)); return true; }
bool CVPU::Unpack_V45(StreamType& stream, uint128& result) { if(stream.GetAvailableReadBytes() < 2) return false; uint16 nColor = 0; stream.Read(&nColor, 2); result.nV0 = ((nColor >> 0) & 0x1F) << 3; result.nV1 = ((nColor >> 5) & 0x1F) << 3; result.nV2 = ((nColor >> 10) & 0x1F) << 3; result.nV3 = ((nColor >> 15) & 0x01) << 7; return true; }
bool CVPU::Unpack_S32(StreamType& stream, uint128& result) { if(stream.GetAvailableReadBytes() < 4) return false; uint32 word = 0; stream.Read(&word, 4); for(unsigned int i = 0; i < 4; i++) { result.nV[i] = word; } return true; }
void CVPU::ProcessPacket(StreamType& stream) { while(stream.GetAvailableReadBytes()) { if(m_STAT.nVPS == 1) { //Command is waiting for more data... ExecuteCommand(stream, m_CODE); if((m_STAT.nVPS == 1) && (stream.GetAvailableReadBytes() != 0)) { //We have data in our FIFO but we still need more than what's available break; } else { continue; } } if(m_STAT.nVEW == 1) { if(IsRunning()) break; m_STAT.nVEW = 0; //Command is waiting for micro-program to end. ExecuteCommand(stream, m_CODE); continue; } #ifdef DELAYED_MSCAL m_previousCODE = m_CODE; #endif stream.Read(&m_CODE, sizeof(CODE)); assert(m_CODE.nI == 0); m_NUM = m_CODE.nNUM; ExecuteCommand(stream, m_CODE); } #ifdef DELAYED_MSCAL if(stream.GetAvailableReadBytes() == 0) { ResumeDelayedMicroProgram(); } #endif }
void CVPU::Cmd_MPG(StreamType& stream, CODE nCommand) { uint32 nSize = stream.GetAvailableReadBytes(); uint32 nNum = (m_NUM == 0) ? (256) : (m_NUM); uint32 nCodeNum = (m_CODE.nNUM == 0) ? (256) : (m_CODE.nNUM); uint32 nTransfered = (nCodeNum - nNum) * 8; nCodeNum *= 8; nNum *= 8; nSize = std::min<uint32>(nNum, nSize); uint32 nDstAddr = (m_CODE.nIMM * 8) + nTransfered; //Check if microprogram is running if(IsRunning()) { m_STAT.nVEW = 1; return; } if(nSize != 0) { uint8* microProgram = reinterpret_cast<uint8*>(alloca(nSize)); stream.Read(microProgram, nSize); //Check if there's a change if(memcmp(m_microMem + nDstAddr, microProgram, nSize) != 0) { m_executor.ClearActiveBlocks(); memcpy(m_microMem + nDstAddr, microProgram, nSize); } } m_NUM -= static_cast<uint8>(nSize / 8); if((m_NUM == 0) && (nSize != 0)) { m_STAT.nVPS = 0; } else { m_STAT.nVPS = 1; } }
bool CVPU::Unpack_V16(StreamType& stream, uint128& result, unsigned int fields, bool zeroExtend) { if(stream.GetAvailableReadBytes() < (fields * 2)) return false; for(unsigned int i = 0; i < fields; i++) { uint32 temp = 0; stream.Read(&temp, 2); if(!zeroExtend) { temp = static_cast<int16>(temp); } result.nV[i] = temp; } return true; }
bool CVPU::Unpack_S8(StreamType& stream, uint128& result, bool zeroExtend) { if(stream.GetAvailableReadBytes() < 1) return false; uint32 temp = 0; stream.Read(&temp, 1); if(!zeroExtend) { temp = static_cast<int8>(temp); } for(unsigned int i = 0; i < 4; i++) { result.nV[i] = temp; } return true; }
void CVPU::Cmd_STMASK(StreamType& stream, CODE command) { if(m_NUM == 0) { m_NUM = 1; } while(m_NUM != 0 && stream.GetAvailableReadBytes()) { stream.Read(&m_MASK, 4); m_NUM--; } if(m_NUM == 0) { m_STAT.nVPS = 0; } else { m_STAT.nVPS = 1; } }
void CVPU::Cmd_STCOL(StreamType& stream, CODE nCommand) { if(m_NUM == 0) { m_NUM = 4; } while(m_NUM != 0 && stream.GetAvailableReadBytes()) { assert(m_NUM <= 4); stream.Read(&m_C[4 - m_NUM], 4); m_NUM--; } if(m_NUM == 0) { m_STAT.nVPS = 0; } else { m_STAT.nVPS = 1; } }
void CVif1::Cmd_DIRECT(StreamType& stream, CODE nCommand) { uint32 nSize = stream.GetAvailableReadBytes(); nSize = std::min<uint32>(m_CODE.nIMM * 0x10, nSize); assert((nSize & 0x0F) == 0); if(nSize != 0) { if(m_directBuffer.size() < nSize) { m_directBuffer.resize(nSize); } auto packet = m_directBuffer.data(); stream.Read(packet, nSize); int32 remainingLength = nSize; while(remainingLength > 0) { uint32 processed = m_gif.ProcessPacket(packet, 0, remainingLength, CGsPacketMetadata(2)); packet += processed; remainingLength -= processed; assert(remainingLength >= 0); } } m_CODE.nIMM -= (nSize / 0x10); if((m_CODE.nIMM == 0) && (nSize != 0)) { m_STAT.nVPS = 0; } else { m_STAT.nVPS = 1; } }