public bool tick(int cycles) { counter += cycles; if (interruptQueue.Count != 0 && IF == 0) { //Console.WriteLine("[CD INT] Queue is " + interruptQueue.Count + " Dequeue = IF | " + interruptQueue.Peek()); IF |= interruptQueue.Dequeue(); } if ((IF & IE) != 0) { //Console.WriteLine("[CD INT] Triggering " + IF.ToString("x8")); return(true); } switch (mode) { case Mode.Idle: if (interruptQueue.Count != 0) //Await some cycles so interrupts are not triggered instant { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE IDLE"); break; case Mode.Seek: if (interruptQueue.Count != 0) { return(false); } counter = 0; mode = Mode.Read; //Console.WriteLine("[CDROM] MODE SEEK"); break; case Mode.Read: if (counter < 33868800 / (isDoubleSpeed ? 150 : 75) || interruptQueue.Count != 0) { return(false); } //if (dataBuffer.Count == 0) { //Console.ForegroundColor = ConsoleColor.DarkGreen; //Console.WriteLine("Reading Loc: " + (Loc - 1)); //Console.ResetColor(); testCDBuffer = cd.Read(isSectorSizeRAW, Loc++); cdBuffer = new Queue <byte>(testCDBuffer); responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x1); counter = 0; //Console.WriteLine("[CDROM] MODE READ"); break; } return(false); }
public bool tick(int cycles) { counter += cycles; if (interruptQueue.Count != 0 && IF == 0) { if (cdDebug) { Console.WriteLine($"[CDROM] Interrupt Queue is size: {interruptQueue.Count} dequeue to IF next Interrupt: {interruptQueue.Peek()}"); } IF |= interruptQueue.Dequeue(); //edgeTrigger = true; } if (/*edgeTrigger &&*/ (IF & IE) != 0) { if (cdDebug) { Console.WriteLine($"[CD INT] Triggering {IF:x8}"); } edgeTrigger = false; isBusy = false; return(true); } switch (mode) { case Mode.Idle: counter = 0; return(false); case Mode.Seek: //Hardcoded seek time... if (counter < 33868800 / 3 || interruptQueue.Count != 0) { return(false); } counter = 0; mode = Mode.Idle; STAT = (byte)(STAT & (~0x40)); responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x2); break; case Mode.Read: case Mode.Play: if (counter < (33868800 / (isDoubleSpeed ? 150 : 75)) || interruptQueue.Count != 0) { return(false); } counter = 0; byte[] rawSector = cd.Read(readLoc++); if (cdDebug) { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine($"Reading readLoc: {readLoc - 1} seekLoc: {seekLoc} size: {rawSector.Length}"); Console.ResetColor(); } if (mode == Mode.Play && !mutedAudio) { applyVolume(rawSector); spu.pushCdBufferSamples(rawSector); return(false); //CDDA isn't delivered to CPU and doesn't raise interrupt } //first 12 are the sync header sectorHeader.mm = rawSector[12]; sectorHeader.ss = rawSector[13]; sectorHeader.ff = rawSector[14]; sectorHeader.mode = rawSector[15]; sectorSubHeader.file = rawSector[16]; sectorSubHeader.channel = rawSector[17]; sectorSubHeader.subMode = rawSector[18]; sectorSubHeader.codingInfo = rawSector[19]; //if (sectorSubHeader.isVideo) Console.WriteLine("is video"); //if (sectorSubHeader.isData) Console.WriteLine("is data"); //if (sectorSubHeader.isAudio) Console.WriteLine("is audio"); if (isXAADPCM && sectorSubHeader.isForm2) { if (sectorSubHeader.isEndOfFile) { if (cdDebug) { Console.WriteLine("[CDROM] XA ON: End of File!"); } //is this even needed? There seems to not be an AutoPause flag like on CDDA //RR4, Castlevania and others hang sound here if hard stoped to STAT 0x2 } if (sectorSubHeader.isRealTime && sectorSubHeader.isAudio) { if (isXAFilter && (filterFile != sectorSubHeader.file || filterChannel != sectorSubHeader.channel)) { if (cdDebug) { Console.WriteLine("[CDROM] XA Filter: file || channel"); } return(false); } if (cdDebug) { Console.WriteLine("[CDROM] XA ON: Realtime + Audio"); //todo flag to pass to SPU? } if (!mutedAudio && !mutedXAADPCM) { byte[] decodedXaAdpcm = XaAdpcm.Decode(rawSector, sectorSubHeader.codingInfo); applyVolume(decodedXaAdpcm); spu.pushCdBufferSamples(decodedXaAdpcm); } return(false); } } //If we arived here sector is supposed to be delivered to CPU so slice out sync and header based on flag if (!isSectorSizeRAW) { rawSector = rawSector.AsSpan().Slice(24, 0x800).ToArray(); } else { rawSector = rawSector.AsSpan().Slice(12).ToArray(); } cdBuffer = new Queue <byte>(rawSector); responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x1); break; case Mode.TOC: if (counter < 33868800 / (isDoubleSpeed ? 150 : 75) || interruptQueue.Count != 0) { return(false); } mode = Mode.Idle; responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x2); counter = 0; break; } return(false); }
public bool tick(int cycles) // this works the CD { counter += cycles; if (counter < 20000) { return(false);; } if (interruptQueue.Count != 0 && IF == 0) { //Console.WriteLine("[CD INT] Queue is " + interruptQueue.Count + " Dequeue = IF | " + interruptQueue.Peek()); IF |= interruptQueue.Dequeue(); //return false; } //if (edgeTrigger) { if ((IF & IE) != 0 /*&& ((InterruptController.loadISTAT() & 0x4) != 0x4)*/) { //Console.WriteLine("[CD INT] Triggering " + IF.ToString("x8")); return(true); } //} //if (interruptQueue.Count != 0 && IF == 0) { // Console.WriteLine("[CD INT] Queue is " + interruptQueue.Count + " Dequeue = IF | " + interruptQueue.Peek()); // IF |= interruptQueue.Dequeue(); //} // //if ((IF & IE) != 0 /*&& ((InterruptController.loadISTAT() & 0x4) != 0x4)*/) { // Console.WriteLine("[CD INT] Triggering " + IF.ToString("x8")); // return true; //} switch (mode) { case Mode.Idle: if (counter < 4000 || interruptQueue.Count != 0) //Await some cycles so interrupts are not triggered instant { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE IDLE"); break; case Mode.Seek: if (counter < 20000 || interruptQueue.Count != 0) { //return false; } mode = Mode.Read; //??? GET RID OF THIS //Console.WriteLine("[CDROM] MODE SEEK"); break; case Mode.Read: if (counter < 200000 || interruptQueue.Count != 0) { return(false); } //i should trigger here and add loc... //if (dataBuffer.Count == 0) { //Console.ForegroundColor = ConsoleColor.DarkGreen; //Console.WriteLine("Reading Loc: " + (Loc - 1)); //Console.ResetColor(); testCDBuffer = cd.Read(isSectorSizeRAW, Loc); Loc++; cdBuffer = new Queue <byte>(testCDBuffer); // } responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x1); counter = 0; //Console.WriteLine("[CDROM] MODE READ"); break; case Mode.Transfer: if (counter < 10000 || interruptQueue.Count != 0) { return(false); } counter = 0; break; } return(false); }
public bool tick(int cycles) { counter += cycles; if (interruptQueue.Count != 0 && IF == 0) { if (cdDebug) { Console.WriteLine($"[CDROM] Interrupt Queue is size: {interruptQueue.Count} dequeue to IF next Interrupt: {interruptQueue.Peek()}"); } IF |= interruptQueue.Dequeue(); //edgeTrigger = true; } if (/*edgeTrigger &&*/ (IF & IE) != 0) { if (cdDebug) { Console.WriteLine($"[CD INT] Triggering {IF:x8}"); } edgeTrigger = false; isBusy = false; return(true); } switch (mode) { case Mode.Idle: if (interruptQueue.Count != 0) //Await some cycles so interrupts are not triggered instant { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE IDLE"); break; case Mode.Seek: if (counter < 100000 || interruptQueue.Count != 0) { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE SEEK"); mode = Mode.Idle; STAT = (byte)(STAT & (~0x40)); break; case Mode.Read: case Mode.Play: if (counter < (33868800 / (isDoubleSpeed ? 150 : 75)) /*&& dataBuffer.Count > 0*/) { return(false); } //if (dataBuffer.Count == 0) { Queue <byte> sector = new Queue <byte>(cd.Read(isSectorSizeRAW, readLoc++)); //if (cdDebug) { //Console.ForegroundColor = ConsoleColor.DarkGreen; //Console.WriteLine($"Reading readLoc: {readLoc - 1} seekLoc: {seekLoc} size: {sector.Count}"); //Console.ResetColor(); //} if (!isSectorSizeRAW) //header tests { sectorHeader.mm = sector.Dequeue(); sectorHeader.ss = sector.Dequeue(); sectorHeader.ff = sector.Dequeue(); sectorHeader.mode = sector.Dequeue(); sectorSubHeader.file = sector.Dequeue(); sectorSubHeader.channel = sector.Dequeue(); sectorSubHeader.subMode = sector.Dequeue(); sectorSubHeader.codingInfo = sector.Dequeue(); //copy of subheader sector.Dequeue(); sector.Dequeue(); sector.Dequeue(); sector.Dequeue(); } //Console.WriteLine(mode); //if ((STAT & 0x80) != 0) Console.WriteLine("is play"); //if (sectorSubHeader.isVideo) Console.WriteLine("is video"); //if (sectorSubHeader.isData) Console.WriteLine("is data"); //if (sectorSubHeader.isAudio) Console.WriteLine("is audio"); if (isXAADPCM && sectorSubHeader.isForm2) { if (sectorSubHeader.isEndOfFile) { if (cdDebug) { Console.WriteLine("[CDROM] XA ON: End of File!"); } //Console.ReadLine(); //mode = Mode.Idle; STAT = 0x2; } if (sectorSubHeader.isRealTime && sectorSubHeader.isAudio) { if (isXAFilter && (filterFile != sectorSubHeader.file || filterChannel != sectorSubHeader.channel)) { return(false); } //Here we should send the XA to SPU but... if (cdDebug) { Console.WriteLine("[CDROM] XA ON: Realtime + Audio >> Skipping as no SPU"); } return(false); } } // } cdBuffer = new Queue <byte>(sector); //Console.WriteLine(cdBuffer.Count); isCDDA = !sectorSubHeader.isData; if (interruptQueue.Count != 0) { return(false); } responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x1); counter = 0; //Console.WriteLine("[CDROM] MODE READ"); break; case Mode.TOC: if (counter < 33868800 / (isDoubleSpeed ? 150 : 75) || interruptQueue.Count != 0) { return(false); } mode = Mode.Idle; responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x2); counter = 0; break; } return(false); }
public bool tick(int cycles) { counter += cycles; if (/*counter > 6000 && */ interruptQueue.Count != 0 && IF == 0) { //Console.WriteLine($"[CDROM] Interrupt Queue is size: {interruptQueue.Count} dequeue to IF next Interrupt: {interruptQueue.Peek()}"); IF |= interruptQueue.Dequeue(); //edgeTrigger = true; } if (/*edgeTrigger && */ (IF & IE) != 0) { //Console.WriteLine($"[CD INT] Triggering {IF:x8}"); //edgeTrigger = false; return(true); } switch (mode) { case Mode.Idle: if (interruptQueue.Count != 0) //Await some cycles so interrupts are not triggered instant { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE IDLE"); break; case Mode.Seek: if (counter < 100000 || interruptQueue.Count != 0) { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE SEEK"); break; case Mode.Read: if (counter < (33868800 / (isDoubleSpeed ? 150 : 75)) /*&& dataBuffer.Count > 0*/) { return(false); } //if (dataBuffer.Count == 0) { //Console.ForegroundColor = ConsoleColor.DarkGreen; //Console.WriteLine($"Reading readLoc: {readLoc} seekLoc: {seekLoc}"); //Console.ResetColor(); cdBuffer = new Queue <byte>(cd.Read(isSectorSizeRAW, readLoc++)); if (interruptQueue.Count != 0) { return(false); } responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x1); counter = 0; //Console.WriteLine("[CDROM] MODE READ"); break; case Mode.TOC: if (counter < 33868800 / (isDoubleSpeed ? 150 : 75) || interruptQueue.Count != 0) { return(false); } mode = Mode.Idle; responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x2); counter = 0; break; } return(false); }
public bool tick(int cycles) { counter += cycles; if (interruptQueue.Count != 0 && IF == 0) { if (cdDebug) { Console.WriteLine($"[CDROM] Interrupt Queue is size: {interruptQueue.Count} dequeue to IF next Interrupt: {interruptQueue.Peek()}"); } IF |= interruptQueue.Dequeue(); //edgeTrigger = true; } if (/*edgeTrigger &&*/ (IF & IE) != 0) { if (cdDebug) { Console.WriteLine($"[CD INT] Triggering {IF:x8}"); } edgeTrigger = false; isBusy = false; return(true); } switch (mode) { case Mode.Idle: if (interruptQueue.Count != 0) //Await some cycles so interrupts are not triggered instant { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE IDLE"); break; case Mode.Seek: if (counter < 100000 || interruptQueue.Count != 0) { return(false); } counter = 0; //Console.WriteLine("[CDROM] MODE SEEK"); mode = Mode.Idle; STAT = (byte)(STAT & (~0x40)); break; case Mode.Read: case Mode.Play: if (counter < (33868800 / (isDoubleSpeed ? 150 : 75)) /*&& dataBuffer.Count > 0*/) { return(false); } //if (dataBuffer.Count == 0) { bool readRaw = isSectorSizeRAW; //During Play, only bit 7,2,1 of Setmode are used, all other Setmode bits are ignored //(that, including bit0, ie. during Play the drive is always in CD-DA mode, regardless of that bit). //Bit7(double speed) should be usually off, although it can be used for a fast forward effect(with audible output). //Bit2(report) activates an optional interrupt for Play, Forward, and Backward commands(see below).Bit1(autopause) pauses play at the end of the track. if (mode == Mode.Play) { readRaw = true; } Queue <byte> sector = new Queue <byte>(cd.Read(readRaw, readLoc++)); //if (cdDebug) { //Console.ForegroundColor = ConsoleColor.DarkGreen; //Console.WriteLine($"Reading readLoc: {readLoc - 1} seekLoc: {seekLoc} size: {sector.Count}"); //Console.ResetColor(); //} if (mode == Mode.Play) { //Console.WriteLine("isSectorsizeRaw " + isSectorSizeRAW); //buffer.AddSamples(sector.ToArray(), 0, sector.Count); //if (waveout.PlaybackState != PlaybackState.Playing) { // waveout.Init(buffer); // waveout.Play(); //} } for (int i = 0; i < 12; i++) { sector.Dequeue(); //dismiss sync header } if (!isSectorSizeRAW) //header tests { sectorHeader.mm = sector.Dequeue(); sectorHeader.ss = sector.Dequeue(); sectorHeader.ff = sector.Dequeue(); sectorHeader.mode = sector.Dequeue(); sectorSubHeader.file = sector.Dequeue(); sectorSubHeader.channel = sector.Dequeue(); sectorSubHeader.subMode = sector.Dequeue(); sectorSubHeader.codingInfo = sector.Dequeue(); //copy of subheader sector.Dequeue(); sector.Dequeue(); sector.Dequeue(); sector.Dequeue(); } //Console.WriteLine(mode); //if ((STAT & 0x80) != 0) Console.WriteLine("is play"); //if (sectorSubHeader.isVideo) Console.WriteLine("is video"); //if (sectorSubHeader.isData) Console.WriteLine("is data"); if (sectorSubHeader.isAudio) { Console.WriteLine("is audio"); } if (isXAADPCM && sectorSubHeader.isForm2) { if (sectorSubHeader.isEndOfFile) { if (cdDebug) { Console.WriteLine("[CDROM] XA ON: End of File!"); } //Console.ReadLine(); //mode = Mode.Idle; STAT = 0x2; } if (sectorSubHeader.isRealTime && sectorSubHeader.isAudio) { if (isXAFilter && (filterFile != sectorSubHeader.file || filterChannel != sectorSubHeader.channel)) { return(false); } if (cdDebug) { Console.WriteLine("[CDROM] XA ON: Realtime + Audio >> Skipping as no SPU"); } //buffer.AddSamples(sector.ToArray(), 0, sector.Count); //if (waveout.PlaybackState != PlaybackState.Playing) { // waveout.Init(XaAdpcm.Decode(buffer)); // waveout.Play(); //} return(false); } } // } cdBuffer = new Queue <byte>(sector); //Console.WriteLine(cdBuffer.Count); isCDDA = !sectorSubHeader.isData; if (interruptQueue.Count != 0) { return(false); } responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x1); counter = 0; //Console.WriteLine("[CDROM] MODE READ"); break; case Mode.TOC: if (counter < 33868800 / (isDoubleSpeed ? 150 : 75) || interruptQueue.Count != 0) { return(false); } mode = Mode.Idle; responseBuffer.Enqueue(STAT); interruptQueue.Enqueue(0x2); counter = 0; break; } return(false); }