Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }