예제 #1
0
        public void Stop()
        {
            // Are we already stopped?
            if (this.State == ConsoleState.Stopped)
            {
                return;
            }

            if (this.workerThread != null && this.workerThread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId)
            {
            }                      // The worker's trying to kill itself? I dunno what to do. Screw it.

            /////////////////
            // Stop the core.

            if (this.State == ConsoleState.Running)
            {
                this.InternalPause();
            }

            // Close the game source.
            try
            {
                this.GameSource.Close();
            }
            catch { }             // Might happen, but I don't care. The game source shouldn't have done that.

            // Done!
            FreeDOCore.Destroy();
            this.State = ConsoleState.Stopped;
        }
예제 #2
0
        public static void LoadState(string fileName)
        {
            BinaryReader reader = null;

            try
            {
                reader = new BinaryReader(new FileStream(fileName, FileMode.Open));
                var saveData = reader.ReadBytes((int)FreeDOCore.GetSaveSize());
                unsafe
                {
                    fixed(byte *saveDataPtr = saveData)
                    {
                        var pointer = new IntPtr(saveDataPtr);

                        FreeDOCore.DoLoad(pointer);
                    }
                }
                reader.Close();
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
        }
예제 #3
0
        private void ExternalInterface_FrameTrigger()
        {
            // We got a signal that multi-task mode has completed a frame!

            // Done with this frame.
            this.isSwapFrameSignaled = true;

            // Use of multi-task mode requires that we ask the core to update our VDL frame for us.
            FreeDOCore.DoFrameMultitask(this.framePtr);
        }
예제 #4
0
        public static void SaveState(string fileName)
        {
            BinaryWriter binaryWriter = null;

            try
            {
                //////////////////////////////////
                // Create directory if it doesn't exist
                string saveDirectory = Path.GetDirectoryName(fileName);
                if (saveDirectory == null)
                {
                    throw new DirectoryNotFoundException("Could not identify containing folder for: " + fileName);
                }

                if (!Directory.Exists(saveDirectory))
                {
                    Directory.CreateDirectory(saveDirectory);
                }

                //////////////////////////////////
                // Save binary data from core emulation.
                binaryWriter = new BinaryWriter(new FileStream(fileName, FileMode.Create));
                var saveData = new byte[FreeDOCore.GetSaveSize()];
                unsafe
                {
                    fixed(byte *saveDataPtr = saveData)
                    {
                        var pointer = new IntPtr(saveDataPtr);

                        FreeDOCore.DoSave(pointer);
                    }
                }
                binaryWriter.Write(saveData);
                binaryWriter.Close();
            }
            finally
            {
                if (binaryWriter != null)
                {
                    binaryWriter.Close();
                }
            }
        }
예제 #5
0
        public unsafe static void CopyBitmap(IntPtr currentFrame, BitmapDefinition bitmapDefinition, int copyWidth, int copyHeight, bool addBlackBorder, bool copyPointlessAlphaByte, bool allowCrop, ScalingAlgorithm scalingAlgorithm)
        {
            Bitmap     bitmapToPrepare = bitmapDefinition.Bitmap;
            BitmapData bitmapData      = bitmapToPrepare.LockBits(new Rectangle(0, 0, bitmapToPrepare.Width, bitmapToPrepare.Height), ImageLockMode.WriteOnly, bitmapToPrepare.PixelFormat);

            int newWidth  = 0;
            int newHeight = 0;

            FreeDOCore.GetFrameBitmap(
                currentFrame
                , bitmapData.Scan0
                , bitmapToPrepare.Width
                , bitmapDefinition.Crop
                , copyWidth
                , copyHeight
                , addBlackBorder
                , copyPointlessAlphaByte
                , allowCrop
                , scalingAlgorithm
                , out newWidth
                , out newHeight);

            bitmapToPrepare.UnlockBits(bitmapData);
        }
예제 #6
0
 public void ReadSector(IntPtr destinationBuffer, int sectorNumber)
 {
     FreeDOCore.SetAnvilFix(2);
     // Set fix for anvil bios
 }
예제 #7
0
        private void WorkerThread()
        {
            const int MAXIMUM_FRAME_COUNT = 100;

            long lastSample   = 0;
            long lastTarget   = 0;
            long targetPeriod = 0;
            int  currentHertz = 12500000;

            bool highResolution = false;

            int overshootSleepThreshold = System.Math.Max(5, TimingHelper.GetResolution());

            // Calculate a default target period in case there are no
            // audio samples for the upcoming frame (which is pretty unlikely).
            targetPeriod = (long)(PerformanceCounter.Frequency / 60.0);

            int sleepTime = 0;

            do
            {
                // We're awake! Wreak havoc!

                /////////////////////
                // If we need to, update some core values.

                // Set arm clock?
                lock (this.clockSpeedSemaphore)
                {
                    if (this.cpuClockHertz.HasValue && currentHertz != this.cpuClockHertz.Value)
                    {
                        currentHertz = this.cpuClockHertz.Value;
                        FreeDOCore.SetArmClock(currentHertz);
                    }
                }

                // Set high resolution mode?
                if (highResolution != this.renderHighResolution.Value)
                {
                    highResolution = this.renderHighResolution.Value;
                    FreeDOCore.SetTextureQuality(highResolution ? 1 : 0);
                }

                // Execute a frame.
                isSwapFrameSignaled = false;
                int lastFrameCount = 0;

                var frameWatch = new PerformanceStopWatch();
                frameWatch.Start();
                do
                {
                    if (doFreeDOMultitask)
                    {
                        FreeDOCore.DoExecuteFrameMultitask(this.framePtr);
                    }
                    else
                    {
                        FreeDOCore.DoExecuteFrame(this.framePtr);
                    }

                    lastFrameCount++;
                } while (isSwapFrameSignaled == false && lastFrameCount < MAXIMUM_FRAME_COUNT);
                frameWatch.Stop();

                ///////////
                // Signal completion.
                var doneWatch = new PerformanceStopWatch();
                doneWatch.Start();
                if (FrameDone != null)
                {
                    FrameDone(this, new EventArgs());
                }
                doneWatch.Stop();

                ///////////
                // Set new target period depending on how many audio samples were pushed.
                if (lastAudioSampleCount > 0)
                {
                    // Figure out how much time was emulated.
                    double lastFrameSeconds = lastAudioSampleCount / (double)44100;

                    // If there were multiple frames, account for this.
                    if (lastFrameCount > 0)
                    {
                        lastFrameSeconds = lastFrameSeconds / lastFrameCount;
                    }

                    targetPeriod = (long)(PerformanceCounter.Frequency * lastFrameSeconds);

                    lastAudioSampleCount = 0;
                }

                ///////////
                // Identify how long to sleep (if at all).
                long currentOvershoot = 0;
                long cheatAmount      = 0;
                if (lastSample == 0)
                {
                    // This is the first sample; this one's a freebee.
                    lastSample = PerformanceCounter.Current;
                    lastTarget = lastSample;                     // Pretend we're right on target!
                    sleepTime  = 0;
                }
                else
                {
                    long currentSample = PerformanceCounter.Current;
                    long currentDelta  = currentSample - lastSample;

                    long currentTarget = lastTarget + targetPeriod * lastFrameCount;
                    currentOvershoot = currentTarget - currentSample;

                    speedCalculator.AddSample((currentDelta / (double)lastFrameCount) / (double)PerformanceCounter.Frequency);

                    // Are we ahead of schedule?
                    if (currentOvershoot > 0)
                    {
                        // We're AHEAD OF schedule.
                        // This is easy. We'll sleep if we're far enough ahead.
                        sleepTime = (int)(((currentOvershoot) / (double)PerformanceCounter.Frequency) * 1000);

                        // However, Our sleeps must always be at least the system's minimum sleep granularity.
                        if (sleepTime < overshootSleepThreshold)
                        {
                            sleepTime = 0;
                        }
                    }
                    else
                    {
                        // We're BEHIND schedule! No sleeping!
                        sleepTime = 0;

                        if (currentOvershoot < -maxLagTicks)
                        {
                            // We're REALLY BEHIND schedule. HOLY SHIT!
                            // There's no way we can catch up. Just "give up" and accept a new target schedule.
                            cheatAmount   = currentOvershoot;
                            currentTarget = currentSample;
                        }
                    }

                    // Save the values for next time.
                    lastSample = currentSample;
                    lastTarget = currentTarget;
                }

                if (cheatAmount != 0)
                {
                    healthCalculator.ReportCheat(cheatAmount);
                }

                // Let the audio plugin know the current "schedule".
                this.audioPlugin.FrameDone(cheatAmount > 0 ? 0 : currentOvershoot, cheatAmount);

                /////////////
                // Sleep if we've been instructed to.
                var sleepWatch = new PerformanceStopWatch();
                sleepWatch.Start();
                if (sleepTime > 0 && !this.stopWorkerSignal)
                {
                    Thread.Sleep(sleepTime);
                }
                sleepWatch.Stop();

                // Some debug output.
                if (FourDO.Utilities.Globals.RunOptions.LogCPUTiming)
                {
                    Trace.WriteLine(string.Format("CpuTiming - Frames:\t{0}\tSleepReq:\t{1:00.00}\tSlept:\t{2:00.00}\tSleepScrewup:\t{3:00.00}\tFrameTm:\t{4:00.00}\tDoneTm:\t{5:00.00}\tTargetOff:\t{6:00.00}\tCheatTm:\t{7:00.00}"
                                                  , lastFrameCount
                                                  , sleepTime
                                                  , sleepWatch.TotalMilliseconds
                                                  , sleepWatch.TotalMilliseconds - sleepTime
                                                  , frameWatch.TotalMilliseconds
                                                  , doneWatch.TotalMilliseconds
                                                  , ((currentOvershoot) / (double)PerformanceCounter.Frequency) * 1000
                                                  , ((cheatAmount) / (double)PerformanceCounter.Frequency) * 1000
                                                  ));
                }
            } while (this.stopWorkerSignal == false);
        }
예제 #8
0
        public void Start(string biosRom1FileName, string biosRom2FileName, IGameSource gameSource, string nvramFileName)
        {
            int fixMode = 0;

            ///////////
            // If they haven't initialized us properly, complain!

            if (!this.maxLagTicks.HasValue)
            {
                throw new InvalidOperationException("Audio buffer not set!");
            }

            if (!this.cpuClockHertz.HasValue)
            {
                throw new InvalidOperationException("CPU Clock speed not set!");
            }

            if (!this.renderHighResolution.HasValue)
            {
                throw new InvalidOperationException("High resolution setting not set!");
            }

            // Are we already started?
            if (this.workerThread != null)
            {
                return;
            }

            this.GameSource = gameSource;

            //////////////
            // Attempt to load Bios #1.
            try
            {
                this.biosRom1Copy = System.IO.File.ReadAllBytes(biosRom1FileName);
            }
            catch
            {
                throw new BadBiosRom1Exception();
            }

            // Also get outta here if it's not the right length.
            if (this.biosRom1Copy.Length != ROM1_SIZE)
            {
                throw new BadBiosRom1Exception();
            }
            if (this.biosRom1Copy[28] == 234)
            {
                FreeDOCore.SetAnvilFix(30);
            }                                                                 //bios anvil
            //////////////
            // Attempt to load Bios #2.

            // If we don't load Bios #2, we'll just use all zeroes.
            this.biosRom2Copy = new byte[ROM2_SIZE];             // Allocate full size to get all 0's

            // Load from file, if a file was chosen
            byte[] biosRom2Bytes = null;
            if (!string.IsNullOrWhiteSpace(biosRom2FileName))
            {
                try
                {
                    biosRom2Bytes = System.IO.File.ReadAllBytes(biosRom2FileName);
                }
                catch
                {
                    throw new BadBiosRom2Exception();
                }

                // Bios #2 is allowed to be less than or equal to the right size.
                // The only example file I know of is less than (912KB) the actual size on the hardware (1MB).
                if (biosRom2Bytes.Length > ROM2_SIZE || biosRom2Bytes.Length == 0)
                {
                    throw new BadBiosRom2Exception();
                }



                // Copy to the member variable.
                biosRom2Bytes.CopyTo(this.biosRom2Copy, 0);
            }

            //////////////
            // Load a copy of the nvram.
            try
            {
                // If we previously had a game open, and they have now loaded
                // a new game, we want to make sure the game that was previously
                // open does not accidentally save.
                lock (nvramCopySemaphore)
                {
                    // Note that we copy to the OLD nvram file name, just in case.
                    if (this.nvramTimer.Enabled == true)
                    {
                        Memory.WriteMemoryDump(this.nvramFileName, this.nvramCopyPtr, NVRAM_SIZE);
                    }

                    this.nvramTimer.Enabled = false;

                    // Read the new NVRAM into memory.
                    Memory.ReadMemoryDump(this.nvramCopy, nvramFileName, NVRAM_SIZE);
                }
            }
            catch
            {
                throw new BadNvramFileException();
            }

            // Freak out if the nvram isn't the right size.
            if (this.nvramCopy.Length != NVRAM_SIZE)
            {
                throw new BadNvramFileException();
            }

            // Remember the file name.
            this.nvramFileName = nvramFileName;

            //////////////
            // Attempt to start up the game source (it is allowed to throw errors).
            try
            {
                this.GameSource.Open();
            }
            catch
            {
                throw new BadGameRomException();
            }

            FreeDOCore.SetFixMode(fixMode);

            /////////////////
            // Initialize the core
            FreeDOCore.Initialize();

            ////////////////
            // Set fix mode
            GameRecord record = GameRegistrar.GetGameRecordById(this.GameSource.GetGameId());

            if (record != null)
            {
                if (
                    record.Id == "F3AF1B13" || // Crash 'n Burn (JP)
                    record.Id == "217344B0"    // Crash 'n Burn (US)

                    )
                {
                    fixMode = fixMode | (int)FixMode.FIX_BIT_TIMING_1;
                }

                if (record.Id == "DBB419FA" || // Street Figthter 2, for intro sync
                    record.Id == "07C32F10" ||// Street Figthter 2, for intro sync
                    record.Id == "5282889F" ||// Street Figthter 2, for intro sync
                    record.Id == "7340307E"   // Street Figthter 2, for intro sync
                    )
                {
                    fixMode = fixMode | (int)FixMode.FIX_BIT_TIMING_2;
                }

                if (record.Id == "CB8EE795" // Dinopark Tycoon
                    )
                {
                    fixMode = fixMode | (int)FixMode.FIX_BIT_TIMING_3;
                }

                if (record.Id == "1A370EBA" || // Microcosm
                    record.Id == "B35C911D"// Microcosm
                    )
                {
                    fixMode = fixMode | (int)FixMode.FIX_BIT_TIMING_5;
                }

                if (record.Id == "0511D3D2" || // Alone in the Dark
                    record.Id == "9F7D72BC" ||// Alone in the Dark
                    record.Id == "E843C635"// Alone in the Dark
                    )
                {
                    fixMode = fixMode | (int)FixMode.FIX_BIT_TIMING_6;
                }

                if (record.Id == "2AABA5B9" || // Samurai Shodown (EU-US)
                    record.Id == "BF61BB32"    // Samurai Shodown (JP)
                    )
                {
                    fixMode = fixMode | (int)FixMode.FIX_BIT_GRAPHICS_STEP_Y;
                }
            }
            FreeDOCore.SetFixMode(fixMode);
            /////////////////
            // Start the core thread
            this.InternalResume(false);
        }