void getFileAndPosForBlockHash(BlockHeader& blk) { BlockFilePosition filePos = { 0, 0 }; //we dont have the file position for this header, let's find it class StopReading : public std::exception { }; const BinaryData& thisHash = blk.getThisHash(); const auto stopIfBlkHeaderRecognized = [&thisHash, &filePos]( const BinaryData &blockheader, const BlockFilePosition &pos, uint32_t blksize ) { filePos = pos; BlockHeader block; BinaryRefReader brr(blockheader); block.unserialize(brr); const HashString blockhash = block.getThisHash(); if (blockhash == thisHash) throw StopReading(); }; try { //at this point, the last blkFile has been scanned for block, so skip it for (int32_t i = blkFiles_.size() - 2; i > -1; i--) { readHeadersFromFile( blkFiles_[i], 0, stopIfBlkHeaderRecognized ); } } catch (StopReading&) { // we're fine } blk.setBlockFileNum(filePos.first); blk.setBlockFileOffset(filePos.second); }
void cdrWrite1(u8 rt) { int i; CDVD_LOG("CD1 write: %x (%s)", rt, CmdName[rt]); cdr.Cmd = rt; cdr.OCUP = 0; #ifdef CDRCMD_DEBUG SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); if (cdr.ParamC) { SysPrintf(" Param[%d] = {", cdr.ParamC); for (i=0;i<cdr.ParamC;i++) SysPrintf(" %x,", cdr.Param[i]); SysPrintf("}\n"); } else SysPrintf("\n"); #endif if (cdr.Ctrl & 0x1) return; switch(cdr.Cmd) { case CdlSync: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlNop: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSetloc: StopReading(); for (i=0; i<3; i++) cdr.SetSector[i] = btoi(cdr.Param[i]); cdr.SetSector[3] = 0; if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) { *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek; } cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlPlay: cdr.Play = 1; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlForward: if (cdr.CurTrack < 0xaa) cdr.CurTrack++; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlBackward: if (cdr.CurTrack > 1) cdr.CurTrack--; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlReadN: cdr.Irq = 0; StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; StartReading(1); break; case CdlStandby: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlStop: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlPause: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x40000); break; case CdlReset: case CdlInit: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlMute: cdr.Muted = 0; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlDemute: cdr.Muted = 1; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSetfilter: cdr.File = cdr.Param[0]; cdr.Channel = cdr.Param[1]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSetmode: CDVD_LOG("Setmode %x", cdr.Param[0]); cdr.Mode = cdr.Param[0]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetmode: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetlocL: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetlocP: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetTN: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetTD: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSeekL: ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSeekP: ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlTest: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlID: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlReadS: cdr.Irq = 0; StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; StartReading(2); break; case CdlReadToc: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; default: CDVD_LOG("Unknown Cmd: %x\n", cdr.Cmd); return; } if (cdr.Stat != NoIntr) iopIntcIrq( 2 ); }
void cdrInterrupt() { u16 Irq = cdr.Irq; int no_busy_error = 0; int start_rotating = 0; int error = 0; int delay; // Reschedule IRQ if (cdr.Stat) { CDR_LOG_I("cdrom: stat hack: %02x %x\n", cdr.Irq, cdr.Stat); CDR_INT(0x1000); return; } cdr.Ctrl &= ~0x80; // default response SetResultSize(1); cdr.Result[0] = cdr.StatP; cdr.Stat = Acknowledge; if (cdr.IrqRepeated) { cdr.IrqRepeated = 0; if (cdr.eCycle > psxRegs.cycle) { CDR_INT(cdr.eCycle); goto finish; } } cdr.Irq = 0; switch (Irq) { case CdlSync: // TOOD: sometimes/always return error? break; case CdlNop: if (cdr.DriveState != DRIVESTATE_LID_OPEN) cdr.StatP &= ~STATUS_SHELLOPEN; no_busy_error = 1; break; case CdlSetloc: break; do_CdlPlay: case CdlPlay: StopCdda(); if (cdr.Seeked == SEEK_PENDING) { // XXX: wrong, should seek instead.. cdr.Seeked = SEEK_DONE; } if (cdr.SetlocPending) { memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; } // BIOS CD Player // - Pause player, hit Track 01/02/../xx (Setloc issued!!) if (cdr.ParamC == 0 || cdr.Param[0] == 0) { CDR_LOG("PLAY Resume @ %d:%d:%d\n", cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2]); } else { int track = btoi( cdr.Param[0] ); if (track <= cdr.ResultTN[1]) cdr.CurTrack = track; CDR_LOG("PLAY track %d\n", cdr.CurTrack); if (CDR_getTD((u8)cdr.CurTrack, cdr.ResultTD) != -1) { cdr.SetSectorPlay[0] = cdr.ResultTD[2]; cdr.SetSectorPlay[1] = cdr.ResultTD[1]; cdr.SetSectorPlay[2] = cdr.ResultTD[0]; } } /* Rayman: detect track changes - fixes logo freeze Twisted Metal 2: skip PREGAP + starting accurate SubQ - plays tracks without retry play Wild 9: skip PREGAP + starting accurate SubQ - plays tracks without retry play */ Find_CurTrack(cdr.SetSectorPlay); ReadTrack(cdr.SetSectorPlay); cdr.TrackChanged = FALSE; if (!Config.Cdda) CDR_play(cdr.SetSectorPlay); // Vib Ribbon: gameplay checks flag cdr.StatP &= ~STATUS_SEEK; cdr.Result[0] = cdr.StatP; cdr.StatP |= STATUS_PLAY; // BIOS player - set flag again cdr.Play = TRUE; CDRMISC_INT( cdReadTime ); start_rotating = 1; break; case CdlForward: // TODO: error 80 if stopped cdr.Stat = Complete; // GameShark CD Player: Calls 2x + Play 2x if( cdr.FastForward == 0 ) cdr.FastForward = 2; else cdr.FastForward++; cdr.FastBackward = 0; break; case CdlBackward: cdr.Stat = Complete; // GameShark CD Player: Calls 2x + Play 2x if( cdr.FastBackward == 0 ) cdr.FastBackward = 2; else cdr.FastBackward++; cdr.FastForward = 0; break; case CdlStandby: if (cdr.DriveState != DRIVESTATE_STOPPED) { error = ERROR_INVALIDARG; goto set_error; } AddIrqQueue(CdlStandby + 0x100, cdReadTime * 125 / 2); start_rotating = 1; break; case CdlStandby + 0x100: cdr.Stat = Complete; break; case CdlStop: if (cdr.Play) { // grab time for current track CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD); cdr.SetSectorPlay[0] = cdr.ResultTD[2]; cdr.SetSectorPlay[1] = cdr.ResultTD[1]; cdr.SetSectorPlay[2] = cdr.ResultTD[0]; } StopCdda(); StopReading(); delay = 0x800; if (cdr.DriveState == DRIVESTATE_STANDBY) delay = cdReadTime * 30 / 2; cdr.DriveState = DRIVESTATE_STOPPED; AddIrqQueue(CdlStop + 0x100, delay); break; case CdlStop + 0x100: cdr.StatP &= ~STATUS_ROTATING; cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; break; case CdlPause: /* Gundam Battle Assault 2: much slower (*) - Fixes boot, gameplay Hokuto no Ken 2: slower - Fixes intro + subtitles InuYasha - Feudal Fairy Tale: slower - Fixes battles */ AddIrqQueue(CdlPause + 0x100, cdReadTime * 3); cdr.Ctrl |= 0x80; break; case CdlPause + 0x100: cdr.StatP &= ~STATUS_READ; cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; break; case CdlInit: AddIrqQueue(CdlInit + 0x100, cdReadTime * 6); no_busy_error = 1; start_rotating = 1; break; case CdlInit + 0x100: cdr.Stat = Complete; break; case CdlMute: cdr.Muted = TRUE; break; case CdlDemute: cdr.Muted = FALSE; break; case CdlSetfilter: cdr.File = cdr.Param[0]; cdr.Channel = cdr.Param[1]; break; case CdlSetmode: no_busy_error = 1; break; case CdlGetmode: SetResultSize(6); cdr.Result[1] = cdr.Mode; cdr.Result[2] = cdr.File; cdr.Result[3] = cdr.Channel; cdr.Result[4] = 0; cdr.Result[5] = 0; no_busy_error = 1; break; case CdlGetlocL: SetResultSize(8); memcpy(cdr.Result, cdr.Transfer, 8); break; case CdlGetlocP: SetResultSize(8); memcpy(&cdr.Result, &cdr.subq, 8); if (!cdr.Play && !cdr.Reading) cdr.Result[1] = 0; // HACK? break; case CdlReadT: // SetSession? // really long AddIrqQueue(CdlReadT + 0x100, cdReadTime * 290 / 4); start_rotating = 1; break; case CdlReadT + 0x100: cdr.Stat = Complete; break; case CdlGetTN: SetResultSize(3); if (CDR_getTN(cdr.ResultTN) == -1) { cdr.Stat = DiskError; cdr.Result[0] |= STATUS_ERROR; } else { cdr.Stat = Acknowledge; cdr.Result[1] = itob(cdr.ResultTN[0]); cdr.Result[2] = itob(cdr.ResultTN[1]); } break; case CdlGetTD: cdr.Track = btoi(cdr.Param[0]); SetResultSize(4); if (CDR_getTD(cdr.Track, cdr.ResultTD) == -1) { cdr.Stat = DiskError; cdr.Result[0] |= STATUS_ERROR; } else { cdr.Stat = Acknowledge; cdr.Result[0] = cdr.StatP; cdr.Result[1] = itob(cdr.ResultTD[2]); cdr.Result[2] = itob(cdr.ResultTD[1]); cdr.Result[3] = itob(cdr.ResultTD[0]); } break; case CdlSeekL: case CdlSeekP: StopCdda(); StopReading(); cdr.StatP |= STATUS_SEEK; /* Crusaders of Might and Magic = 0.5x-4x - fix cutscene speech start Eggs of Steel = 2x-? - fix new game Medievil = ?-4x - fix cutscene speech Rockman X5 = 0.5-4x - fix capcom logo */ CDRMISC_INT(cdr.Seeked == SEEK_DONE ? 0x800 : cdReadTime * 4); cdr.Seeked = SEEK_PENDING; start_rotating = 1; break; case CdlTest: switch (cdr.Param[0]) { case 0x20: // System Controller ROM Version SetResultSize(4); memcpy(cdr.Result, Test20, 4); break; case 0x22: SetResultSize(8); memcpy(cdr.Result, Test22, 4); break; case 0x23: case 0x24: SetResultSize(8); memcpy(cdr.Result, Test23, 4); break; } no_busy_error = 1; break; case CdlID: AddIrqQueue(CdlID + 0x100, 20480); break; case CdlID + 0x100: SetResultSize(8); cdr.Result[0] = cdr.StatP; cdr.Result[1] = 0; cdr.Result[2] = 0; cdr.Result[3] = 0; // 0x10 - audio | 0x40 - disk missing | 0x80 - unlicensed if (CDR_getStatus(&stat) == -1 || stat.Type == 0 || stat.Type == 0xff) { cdr.Result[1] = 0xc0; } else { if (stat.Type == 2) cdr.Result[1] |= 0x10; if (CdromId[0] == '\0') cdr.Result[1] |= 0x80; } cdr.Result[0] |= (cdr.Result[1] >> 4) & 0x08; strncpy((char *)&cdr.Result[4], "PCSX", 4); cdr.Stat = Complete; break; case CdlReset: // yes, it really sets STATUS_SHELLOPEN cdr.StatP |= STATUS_SHELLOPEN; cdr.DriveState = DRIVESTATE_RESCAN_CD; CDRLID_INT(20480); no_busy_error = 1; start_rotating = 1; break; case CdlGetQ: // TODO? CDR_LOG_I("got CdlGetQ\n"); break; case CdlReadToc: AddIrqQueue(CdlReadToc + 0x100, cdReadTime * 180 / 4); no_busy_error = 1; start_rotating = 1; break; case CdlReadToc + 0x100: cdr.Stat = Complete; no_busy_error = 1; break; case CdlReadN: case CdlReadS: if (cdr.SetlocPending) { memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; } Find_CurTrack(cdr.SetSectorPlay); if ((cdr.Mode & MODE_CDDA) && cdr.CurTrack > 1) // Read* acts as play for cdda tracks in cdda mode goto do_CdlPlay; cdr.Reading = 1; cdr.FirstSector = 1; // Fighting Force 2 - update subq time immediately // - fixes new game ReadTrack(cdr.SetSectorPlay); // Crusaders of Might and Magic - update getlocl now // - fixes cutscene speech { u8 *buf = CDR_getBuffer(); if (buf != NULL) memcpy(cdr.Transfer, buf, 8); } /* Duke Nukem: Land of the Babes - seek then delay read for one frame - fixes cutscenes C-12 - Final Resistance - doesn't like seek */ if (cdr.Seeked != SEEK_DONE) { cdr.StatP |= STATUS_SEEK; cdr.StatP &= ~STATUS_READ; // Crusaders of Might and Magic - use short time // - fix cutscene speech (startup) // ??? - use more accurate seek time later CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); } else { cdr.StatP |= STATUS_READ; cdr.StatP &= ~STATUS_SEEK; CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); } cdr.Result[0] = cdr.StatP; start_rotating = 1; break; default: CDR_LOG_I("Invalid command: %02x\n", Irq); error = ERROR_INVALIDCMD; // FALLTHROUGH set_error: SetResultSize(2); cdr.Result[0] = cdr.StatP | STATUS_ERROR; cdr.Result[1] = error; cdr.Stat = DiskError; break; } if (cdr.DriveState == DRIVESTATE_STOPPED && start_rotating) { cdr.DriveState = DRIVESTATE_STANDBY; cdr.StatP |= STATUS_ROTATING; } if (!no_busy_error) { switch (cdr.DriveState) { case DRIVESTATE_LID_OPEN: case DRIVESTATE_RESCAN_CD: case DRIVESTATE_PREPARE_CD: SetResultSize(2); cdr.Result[0] = cdr.StatP | STATUS_ERROR; cdr.Result[1] = ERROR_NOT_READY; cdr.Stat = DiskError; break; } } finish: setIrq(); cdr.ParamC = 0; #ifdef CDR_LOG_CMD_IRQ { int i; SysPrintf("CDR IRQ %d cmd %02x stat %02x: ", !!(cdr.Stat & cdr.Reg2), Irq, cdr.Stat); for (i = 0; i < cdr.ResultC; i++) SysPrintf("%02x ", cdr.Result[i]); SysPrintf("\n"); } #endif }
// timing used in this function was taken from tests on real hardware // (yes it's slow, but you probably don't want to modify it) void cdrLidSeekInterrupt() { switch (cdr.DriveState) { default: case DRIVESTATE_STANDBY: cdr.StatP &= ~STATUS_SEEK; if (CDR_getStatus(&stat) == -1) return; if (stat.Status & STATUS_SHELLOPEN) { StopCdda(); cdr.DriveState = DRIVESTATE_LID_OPEN; CDRLID_INT(0x800); } break; case DRIVESTATE_LID_OPEN: if (CDR_getStatus(&stat) == -1) stat.Status &= ~STATUS_SHELLOPEN; // 02, 12, 10 if (!(cdr.StatP & STATUS_SHELLOPEN)) { StopReading(); cdr.StatP |= STATUS_SHELLOPEN; // could generate error irq here, but real hardware // only sometimes does that // (not done when lots of commands are sent?) CDRLID_INT(cdReadTime * 30); break; } else if (cdr.StatP & STATUS_ROTATING) { cdr.StatP &= ~STATUS_ROTATING; } else if (!(stat.Status & STATUS_SHELLOPEN)) { // closed now CheckCdrom(); // cdr.StatP STATUS_SHELLOPEN is "sticky" // and is only cleared by CdlNop cdr.DriveState = DRIVESTATE_RESCAN_CD; CDRLID_INT(cdReadTime * 105); break; } // recheck for close CDRLID_INT(cdReadTime * 3); break; case DRIVESTATE_RESCAN_CD: cdr.StatP |= STATUS_ROTATING; cdr.DriveState = DRIVESTATE_PREPARE_CD; // this is very long on real hardware, over 6 seconds // make it a bit faster here... CDRLID_INT(cdReadTime * 150); break; case DRIVESTATE_PREPARE_CD: cdr.StatP |= STATUS_SEEK; cdr.DriveState = DRIVESTATE_STANDBY; CDRLID_INT(cdReadTime * 26); break; } }
void cdrWrite1(unsigned char rt) { int i; #ifdef CDR_LOG CDR_LOG("cdrWrite1() Log: CD1 write: %x (%s)\n", rt, CmdName[rt]); #endif // psxHu8(0x1801) = rt; cdr.Cmd = rt; cdr.OCUP = 0; #ifdef CDRCMD_DEBUG SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]); if (cdr.ParamC) { SysPrintf(" Param[%d] = {", cdr.ParamC); for (i=0;i<cdr.ParamC;i++) SysPrintf(" %x,", cdr.Param[i]); SysPrintf("}\n"); } else SysPrintf("\n"); #endif if (cdr.Ctrl & 0x1) return; switch(cdr.Cmd) { case CdlSync: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlNop: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSetloc: StopReading(); cdr.Seeked = 0; for (i=0; i<3; i++) cdr.SetSector[i] = btoi(cdr.Param[i]); cdr.SetSector[3] = 0; /* if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) { *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek; }*/ cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlPlay: if (!cdr.SetSector[0] && !cdr.SetSector[1] && !cdr.SetSector[2]) { if (CDR_getTN(cdr.ResultTN) != -1) { if (cdr.CurTrack > cdr.ResultTN[1]) cdr.CurTrack = cdr.ResultTN[1]; if (CDR_getTD((unsigned char)(cdr.CurTrack), cdr.ResultTD) != -1) { int tmp = cdr.ResultTD[2]; cdr.ResultTD[2] = cdr.ResultTD[0]; cdr.ResultTD[0] = tmp; if (!Config.Cdda) CDR_play(cdr.ResultTD); } } } else if (!Config.Cdda) CDR_play(cdr.SetSector); cdr.Play = 1; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlForward: if (cdr.CurTrack < 0xaa) cdr.CurTrack++; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlBackward: if (cdr.CurTrack > 1) cdr.CurTrack--; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlReadN: cdr.Irq = 0; StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; StartReading(1); break; case CdlStandby: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlStop: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlPause: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x40000); break; case CdlReset: case CdlInit: StopCdda(); StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlMute: cdr.Muted = 0; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlDemute: cdr.Muted = 1; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSetfilter: cdr.File = cdr.Param[0]; cdr.Channel = cdr.Param[1]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSetmode: #ifdef CDR_LOG CDR_LOG("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]); #endif cdr.Mode = cdr.Param[0]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetmode: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetlocL: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetlocP: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetTN: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlGetTD: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSeekL: // ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlSeekP: // ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlTest: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlID: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; case CdlReadS: cdr.Irq = 0; StopReading(); cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; StartReading(2); break; case CdlReadToc: cdr.Ctrl|= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); break; default: #ifdef CDR_LOG CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd); #endif return; } if (cdr.Stat != NoIntr) { psxHu32ref(0x1070)|= SWAP32((u32)0x4); psxRegs.interrupt|= 0x80000000; } }
// find the location of the first block that is not in @p bc BlockFilePosition findFirstUnrecognizedBlockHeader( Blockchain &bc ) { map<HashString, BlockHeader> &allHeaders = bc.allHeaders(); size_t index=0; for (; index < blkFiles_.size(); index++) { const BinaryData hash = getFirstHash(blkFiles_[index]); if (allHeaders.find(hash) == allHeaders.end()) { // not found in this file if (index == 0) return { 0, 0 }; break; } } if (index == 0) return { 0, 0 }; index--; // ok, now "index" is for the last blkfile that we found a header in // now lets linearly search this file until we find an unrecognized blk BlockFilePosition foundAtPosition{ 0, 0 }; bool foundTopBlock = false; auto topBlockHash = bc.top().getThisHash(); const auto stopIfBlkHeaderRecognized = [&allHeaders, &foundAtPosition, &foundTopBlock, &topBlockHash] ( const BinaryData &blockheader, const BlockFilePosition &pos, uint32_t blksize ) { // always set our position so that eventually it's at the end foundAtPosition = pos; BlockHeader block; BinaryRefReader brr(blockheader); block.unserialize(brr); const HashString blockhash = block.getThisHash(); auto bhIter = allHeaders.find(blockhash); if(bhIter == allHeaders.end()) throw StopReading(); if (bhIter->second.getThisHash() == topBlockHash) foundTopBlock = true; bhIter->second.setBlockFileNum(pos.first); bhIter->second.setBlockFileOffset(pos.second); }; uint64_t returnedOffset = UINT64_MAX; try { returnedOffset = readHeadersFromFile( blkFiles_[index], 0, stopIfBlkHeaderRecognized ); } catch (StopReading&) { // we're fine } // but we never find the genesis block, because // it always appears in Blockchain even if unloaded, and // we need to load it if (foundAtPosition.first == 0 && foundAtPosition.second==293) return { 0, 0 }; if (returnedOffset != UINT64_MAX) foundAtPosition.second = returnedOffset; if (!foundTopBlock) { LOGWARN << "Couldn't find top block hash in last seen blk file." " Searching for it further down the chain"; //Couldn't find the top header in the last seen blk file. Since Core //0.10, this can be an indicator of missing hashes. Let's find the //the top block header in file. BlockFilePosition topBlockPos(0, 0); auto checkBlkHash = [&topBlockHash, &topBlockPos] (const BinaryData &rawBlock, const BlockFilePosition &pos, uint32_t blksize)->void { BlockHeader bhUnser(rawBlock); if (bhUnser.getThisHash() == topBlockHash) { topBlockPos = pos; throw StopReading(); } }; bool _foundTopBlock = false; int32_t fnum = blkFiles_.size(); if (fnum > 0) fnum--; try { for (; fnum > -1; fnum--) readHeadersFromFile(blkFiles_[fnum], 0, checkBlkHash); } catch (StopReading&) { _foundTopBlock = true; // we're fine } if (!_foundTopBlock) { //can't find the top header, let's just rescan all headers LOGERR << "Failed to find last known top block hash in " "blk files. Rescanning all headers"; return BlockFilePosition(0, 0); } //Check this file to see if we are missing any block hashes in there auto& f = blkFiles_[foundAtPosition.first]; try { readHeadersFromFile(f, 0, stopIfBlkHeaderRecognized); } catch (StopReading&) { //so we are indeed missing some block headers. Let's just scan the //blocks folder for headers foundAtPosition.first = 0; foundAtPosition.second = 0; LOGWARN << "Inconsistent headers DB, attempting repairs"; } } return foundAtPosition; }