📄 processor.cc
字号:
ifo->getNumberOfSPUStreams(position.isInMenu()); if (numSPUStreams==0) { return false; } unsigned spuStreamNumber = getSPRM().getSPSTN(); bool display = (spuStreamNumber&0x40)==0x40 || spuStreamNumber==62 || spuStreamNumber==63; spuStreamNumber &= 0x3f; if (reversed) { if (spuStreamNumber>31) { spuStreamNumber = numSPUStreams - 1; } else if (spuStreamNumber>0) { --spuStreamNumber; } else { spuStreamNumber = display ? 63 : 62; } } else { if (spuStreamNumber>31) { spuStreamNumber = 0; } else if ((spuStreamNumber+1)<numSPUStreams) { ++spuStreamNumber; } else { spuStreamNumber = display ? 63 : 62; } } if (spuStreamNumber<=31 && display) { spuStreamNumber |= 0x40; } Log::debug("dvd::vm::Processor::nextSPUStream: new SPU stream: %u\n", spuStreamNumber); state.setSPRValue(SPRM::SPSTN, spuStreamNumber); return true;}//------------------------------------------------------------------------------void Processor::execute(const Instruction* instruction, size_t length){ scheduler.addInstructionSet(instruction, length); scheduler.run();}//------------------------------------------------------------------------------void Processor::clearBranches(){ numberOfBranches = 0;}//------------------------------------------------------------------------------bool Processor::hasBranched(){ bool branched = numberOfBranches>0; clearBranches(); return branched;}//------------------------------------------------------------------------------unsigned Processor::mapAudioStreamNumber(unsigned streamNo, unsigned languageCode, const IFO* ifo, PGC pgc, unsigned& candidate) const{ unsigned streamNumber = pgc.getAudioStreamNumber(streamNo); if (streamNumber!=PGC::INVALID_STREAM_NUMBER) { if (candidate==PGC::INVALID_STREAM_NUMBER) { candidate = streamNumber; } if (languageCode!=0xffff) { bool inMenu = getPosition().isInMenu(); if (streamNumber<ifo->getNumberOfAudioStreams(inMenu)) { AudioStreamAttributes audioStreamAttributes = ifo->getAudioStreamAttributes(inMenu, streamNumber); if (audioStreamAttributes.getLanguageCode()!=languageCode) { streamNumber = PGC::INVALID_STREAM_NUMBER; } } else { streamNumber = PGC::INVALID_STREAM_NUMBER; } } } return streamNumber;}//------------------------------------------------------------------------------unsigned Processor::mapSPUStreamNumber(unsigned streamNo, aspectRatio_t aspectRatio, displayFormat_t displayFormat, unsigned languageCode, const IFO* ifo, PGC pgc, unsigned& candidate) const{ unsigned streamNumber = pgc.getSPUStreamNumber(streamNo, aspectRatio, displayFormat); if (streamNumber!=PGC::INVALID_STREAM_NUMBER) { if (candidate==PGC::INVALID_STREAM_NUMBER) { candidate = streamNumber; } if (languageCode!=0xffff) { bool inMenu = getPosition().isInMenu(); if (streamNumber<ifo->getNumberOfSPUStreams(inMenu)) { SPUStreamAttributes spuStreamAttributes = ifo->getSPUStreamAttributes(inMenu, streamNumber); if (spuStreamAttributes.getLanguageCode()!=languageCode) { streamNumber = PGC::INVALID_STREAM_NUMBER; } } else { streamNumber = PGC::INVALID_STREAM_NUMBER; } } } return streamNumber;}//------------------------------------------------------------------------------void Processor::setPosition(const Position& position){ state.setPosition(position);}//------------------------------------------------------------------------------void Processor::process(const Instruction* instruction){ switch(instruction->getType()) { case Instruction::SPECIAL: executeSpecial(instruction); break; case Instruction::BRANCH: executeBranch(instruction); break; case Instruction::SETSYSREG: executeSetSysReg(instruction); break; case Instruction::SET: executeSet(instruction); break; case Instruction::SETCLNK: executeSetCLnk(instruction); break; case Instruction::CSETCLNK: executeCSetCLnk(instruction); break; case Instruction::CMPSETLNK: executeCmpSetLnk(instruction); break; default: Log::error("dvd::vm::Processor::process: invalid instruction type: %u\n", (unsigned)instruction->getType()); scheduler.addStep(); break; }}//------------------------------------------------------------------------------void Processor::executeSpecial(const Instruction* instruction){ if (!evaluateSpecialCondition(instruction)) { scheduler.addStep(); return; } switch(instruction->getSpecCmd()) { case Instruction::BREAK: scheduler.addBreak(); break; case Instruction::SETTMPPLVL: /// FIXME: we should ask for password based in the parental level /// for now, it just succeeds (we trust ourselves and our children) state.setSPRValue(SPRM::PLT, instruction->operand3.getLVL()); // We should goto after successfully setting the parental level case Instruction::GOTO: scheduler.addGoto(instruction->operand3.getLineNumber()); break; default: Log::error("dvd::vm::Processor::executeSpecial: invalid special command: %u\n", (unsigned)instruction->getSpecCmd()); scheduler.addFirstPlayPGC(); break; case Instruction::NOP: scheduler.addStep(); break; }}//------------------------------------------------------------------------------void Processor::executeBranch(const Instruction* instruction){ if (instruction->isDirect()) { executeJumpCall(instruction); } else { executeLink(instruction); }}//------------------------------------------------------------------------------void Processor::executeLink(const Instruction* instruction){ if (evaluateLinkCondition(instruction)) { executeLinkUnconditionally(instruction); } else { scheduler.addStep(); }} //------------------------------------------------------------------------------void Processor::executeLinkUnconditionally(const Instruction* instruction){ TargetPosition targetPosition(state.getPosition()); ++numberOfBranches; switch(instruction->getLinkCmd()) { case Instruction::LINKSUBSET: executeLinkSubset(instruction); break; case Instruction::LINKPGCN: if (targetPosition.enterPGC(instruction->operand3.getPGCN())) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Instruction::LINKPTTN: if (targetPosition.enterPTT(state.getSPRValue(SPRM::vtsTitleNumber), // FIXME: use a more scientific approach here instruction->operand3.getPTTN())) { unsigned buttonNumber = instruction->operand3.getHLBN(); if (buttonNumber>0) { state.setHighlightedButtonNumber(buttonNumber); } scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Instruction::LINKPGN: // FIXME: the same as above if (targetPosition.enterProgram(instruction->operand3.getPGN())) { unsigned buttonNumber = instruction->operand3.getHLBN(); if (buttonNumber>0) { state.setHighlightedButtonNumber(buttonNumber); } scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Instruction::LINKCN: // FIXME: the same as above if (targetPosition.enterCell(instruction->operand3.getCN())) { unsigned buttonNumber = instruction->operand3.getHLBN(); if (buttonNumber>0) { state.setHighlightedButtonNumber(buttonNumber); } scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; default: Log::error("dvd::vm::Processor::executeLinkUnconditionally: invalid link command: %u\n", (unsigned)instruction->getLinkCmd()); scheduler.addFirstPlayPGC(); break; case Instruction::LINK_NOP: --numberOfBranches; scheduler.addStep(); break; }}//------------------------------------------------------------------------------bool Processor::linkPreviousCell(TargetPosition& targetPosition){ if (!targetPosition.enterPreviousCell()) { do { if (!targetPosition.enterPreviousPGC()) { return false; } } while(!targetPosition.enterLastCell()); } return true;}//------------------------------------------------------------------------------void Processor::executeLinkSubset(const Instruction* instruction){ TargetPosition targetPosition(state.getPosition()); switch(instruction->operand3.getLinkType()) { case Operand3::TOPCELL: targetPosition.repeatCell(); scheduler.flush(); scheduler.addSetPosition(targetPosition); break; case Operand3::NEXTCELL: if (targetPosition.enterNextCell()) { scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { if (targetPosition.enterNextPGC()) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } scheduler.addPGCPostCommands(state.getPosition()); } break; case Operand3::PREVCELL: if (linkPreviousCell(targetPosition)) { scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Operand3::TOPPG: targetPosition.repeatProgram(); scheduler.flush(); scheduler.addSetPosition(targetPosition); break; case Operand3::NEXTPG: if (targetPosition.enterNextProgram()) { scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { if (targetPosition.enterNextPGC()) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } scheduler.addPGCPostCommands(state.getPosition()); // FIXME: same as for NEXTCELL } break; case Operand3::PREVPG: if (targetPosition.enterPreviousProgram()) { scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { if (targetPosition.enterPreviousPGC()) { targetPosition.enterLastProgram(); scheduler.flush(); scheduler.addSetPosition(targetPosition); } else { scheduler.addFirstPlayPGC(); } // FIXME: almost the same as PREVCELL } case Operand3::TOPPGC: // FIXME: this is almost the same as for LINKPGCN if (targetPosition.enterProgram(1)) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Operand3::NEXTPGC: // FIXME: this is almost the same as for LINKPGCN if (targetPosition.enterNextPGC()) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Operand3::PREVPGC: // FIXME: this is almost the same as for LINKPGCN if (targetPosition.enterPreviousPGC()) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Operand3::GOUPPGC: // FIXME: this is almost the same as for LINKPGCN if (targetPosition.enterGoUpPGC()) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Operand3::TAILPGC: scheduler.addFirstPlayPGC(); // FIXME: Fallback, if the POST commands // would not jump scheduler.addPGCPostCommands(state.getPosition()); break; case Operand3::RSM: if (!state.resume()) { scheduler.addFirstPlayPGC(); } break; default: Log::error("dvd::vm::Processor::executeLinkSubset: Invalid link subset type: %u\n", (unsigned)instruction->operand3.getLinkType()); scheduler.addFirstPlayPGC(); return; case Operand3::LINK_NOP: --numberOfBranches; scheduler.addStep(); return; } unsigned buttonNumber = instruction->operand3.getHLBN(); if (buttonNumber>0) { state.setHighlightedButtonNumber(buttonNumber); }}//------------------------------------------------------------------------------void Processor::executeJumpCall(const Instruction* instruction){ if (!evaluateJumpCallCondition(instruction)) { scheduler.addStep(); return; } TargetPosition targetPosition(state.getPosition()); ++numberOfBranches; switch(instruction->getJumpCallCmd()) { case Instruction::EXIT: Log::debug("dvd::vm::Processor::executeJumpCall: EXIT instruction hit\n"); if (Config::get().quitOnExit) { scheduler.flush(); targetPosition.exit(); scheduler.addSetPosition(targetPosition); } else { scheduler.addFirstPlayPGC(); } break; case Instruction::JUMPTT: if (targetPosition.enterTT(instruction->operand2.getTTN())) { scheduler.addStartPGC(targetPosition); } else { scheduler.addFirstPlayPGC(); } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -