Пример #1
0
        public GPGX(CoreComm comm, byte[] rom, IEnumerable <Disc> cds, object settings, object syncSettings)
        {
            ServiceProvider = new BasicServiceProvider(this);
            // this can influence some things internally (autodetect romtype, etc)
            string romextension = "GEN";

            // three or six button?
            // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds

            //hack, don't use
            if (rom != null && rom.Length > 32 * 1024 * 1024)
            {
                throw new InvalidOperationException("ROM too big!  Did you try to load a CD as a ROM?");
            }

            _elf = new PeRunner(new PeRunnerOptions
            {
                Path                       = comm.CoreFileProvider.DllPath(),
                Filename                   = "gpgx.wbx",
                SbrkHeapSizeKB             = 512,
                SealedHeapSizeKB           = 36 * 1024,
                InvisibleHeapSizeKB        = 4 * 1024,
                PlainHeapSizeKB            = 64 + 1024,
                MmapHeapSizeKB             = 1 * 1024,
                SkipCoreConsistencyCheck   = comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck),
                SkipMemoryConsistencyCheck = comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck),
            });

            using (_elf.EnterExit())
            {
                Core          = BizInvoker.GetInvoker <LibGPGX>(_elf, _elf, CallingConventionAdapters.Waterbox);
                _syncSettings = (GPGXSyncSettings)syncSettings ?? new GPGXSyncSettings();
                _settings     = (GPGXSettings)settings ?? new GPGXSettings();

                CoreComm = comm;

                LoadCallback = new LibGPGX.load_archive_cb(load_archive);

                _romfile = rom;

                if (cds != null)
                {
                    _cds               = cds.ToArray();
                    _cdReaders         = cds.Select(c => new DiscSectorReader(c)).ToArray();
                    cd_callback_handle = new LibGPGX.cd_read_cb(CDRead);
                    Core.gpgx_set_cdd_callback(cd_callback_handle);
                    DriveLightEnabled = true;
                }

                LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
                LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;

                switch (_syncSettings.ControlType)
                {
                case ControlType.None:
                default:
                    break;

                case ControlType.Activator:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    break;

                case ControlType.Normal:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.OnePlayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.Xea1p:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P;
                    break;

                case ControlType.Teamplayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    break;

                case ControlType.Wayplay:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    break;

                case ControlType.Mouse:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    // seems like mouse in port 1 would be supported, but not both at the same time
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE;
                    break;
                }

                if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _syncSettings.GetNativeSettings()))
                {
                    throw new Exception($"{nameof(Core.gpgx_init)}() failed");
                }

                {
                    int fpsnum = 60;
                    int fpsden = 1;
                    Core.gpgx_get_fps(ref fpsnum, ref fpsden);
                    VsyncNumerator   = fpsnum;
                    VsyncDenominator = fpsden;
                    Region           = VsyncNumerator / VsyncDenominator > 55 ? DisplayType.NTSC : DisplayType.PAL;
                }

                // when we call Seal, ANY pointer passed from managed code must be 0.
                // this is so the initial state is clean
                // the only two pointers set so far are LoadCallback, which the core zeroed itself,
                // and CdCallback
                Core.gpgx_set_cdd_callback(null);
                _elf.Seal();
                Core.gpgx_set_cdd_callback(cd_callback_handle);

                SetControllerDefinition();

                // pull the default video size from the core
                UpdateVideo();

                SetMemoryDomains();

                _inputCallback = new LibGPGX.input_cb(input_callback);
                Core.gpgx_set_input_callback(_inputCallback);

                // process the non-init settings now
                PutSettings(_settings);

                //TODO - this hits performance, we need to make it controllable
                CDCallback = new LibGPGX.CDCallback(CDCallbackProc);

                InitMemCallbacks();
                KillMemCallbacks();

                _tracer = new GPGXTraceBuffer(this, _memoryDomains, this);
                (ServiceProvider as BasicServiceProvider).Register <ITraceable>(_tracer);
            }

            _romfile = null;
        }