Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / WPF

4K (2160p) resolution for PS1, PS2, PSP games

Rate me:
Please Sign up or sign in to vote.
5.00/5 (13 votes)
2 Aug 2020CPOL29 min read 56.5K   24   2
Clone of PCSX/PCSX2/PPSSPP emulator for Windows 10 on WPF/C# with "touch" control
This article presents my new project for cloning and research of PCSX2 PlayStation 2 emulator for Windows 10 on WPF/C#. The purpose of this project is simplification of the original project for more friendly user interface.

Table of Contents

Image 1

Background

The main purpose of this project is to redesign the original PCSX2 for making more simple and friendly user interface for users without complex structure of control component. The original project has complex user interface for regular users (in my view). It has power tools for creating "patches" for game, but I, as a gamer, do not need all of them - I need only a couple buttons for launching my favorite game. Another purpose is to add a touch screen control for Windows 10.

Brief PCSX2 Review

Omega Red PS2 emulator is a clone of the original PCSX2 project. It has a significant changing in graphic user interface, but it can be difficult to understand all these have made changes without the context of the original project.

So, the original project is a result of the long time working of the PCSX2 team. It emulates hardware part of PlayStation 2 game console on x86 CPU for Windows, Linux and MacOS. It includes Emotion Engine MIPS R5900 and I/O processor MIPS R3000 software translators which convert those sets of commands into Intel x86 set of commands. However, the difference between the CPU architectures leads to defining three main execution threads: "EE Core" for execution main set of MIPS R5900's and MIPS R3000's commands; "MTVU" for execution set of 3D vector operations from VU1 commands; "MTGS" for execution commands of the Graphics Synthesizer processor. This threading model allows use of three or more core CPUs in an effective way.

On the level of code, PCSX2 is based on frameworks wxWidgets and pthreads4w. wxWidgets is a framework for creating easy ported GUI. pthreads4w is a framework for defining Unix thread's interface in Windows OS for compatibleness with Unix code.

The last moment is an architect of application. PCSX2 has one of the main execution applications with the loading of plugins. As a result, schema can be presented by the next way:

Image 2

My View of the Problem

In my view, the original project is too complex. It includes tools for debugging code, creating "patches", printout into logs, configuration of CPU translators, configuration of plugins and others. I think that a more simple version in light style can make it easy for using. The other moment is controlling by "touch" schema - I really would like to take my light Surface Pro and spend some time on playing in Final Fantasy X or Final Fantasy XII, but GUI in "Win95" style and the need to use an external game pad "kills game" (embedded touch keyboard is useless).

What Have I Done?

So, what have I done? I have decided to write a clone version of PCSX2 on WPF/C# GUI. WPF is a flexible framework and allows to write code for correct interacting with "touch" screens. However, WPF framework is based on managed code and cannot be effective for directly using in translator code. It leads to the next solution - write the new C DLL library which will contain the minimum needed code for working of the emulator. It has become a significant problem - the original PCSX2 project is an application with the mixed architecture - it is very difficult to separate a "business" logic - emulator core from "thin" client - user interface. This problem has become worse because the original code uses classes and structures from wxWidgets in almost each source file - it binds wxWidgets with PCSX2 very tight. Removing dependency from wxWidgets needs rewriting almost all original source files - it is too much for a hobby project and it will lose compatibility with the original PCSX2 project on the level of the static linking - any modification of the original code needs to copy and modify manually into the code in the new emulator.

Stub wxWidget

In my view, there is only one suitable decision - write a simple framework which includes the same static linking interface as wxWidgets, but implements the needed functionality by C++ STD code. It looks like a huge amount of work, but it is not. Removing dependency to wxWidgets from PCSX2 allows to mark code which is related to the GUI part of project, and remove it from the code. As a result, "Framework" includes only 12 source files. Most of them are "stub" files - they define classes according to the interface of wxWidgets, but do not include executable code. The code of the emulator core is UNBOUNDED from wxWidgets framework.

Image 3

Creating PCSX2Lib

I wrote previously that the main part of this project was finding code of the original PCSX2 which can be named as "Core" or "Kernel". After some research, I found files which can be named in this way - these files can work without specific context of the GUI and File System.

Image 4

Of course, this "Core" cannot work by itself (it is DLL), but it can be used by any Framework in any programming language which CAN LOAD AND LINK C DYNAMIC LIBRARIES. C# and WPF is a suitable framework for this purpose and I am faced with the problem to define correct C interface for PCSX2Lib.dll. Code of PCSX2Lib.dll is very difficult for understanding, and I think that for most readers of this article, it can be more interesting to review C interface of this library and understand the purpose of each of the exported functions.

C++
LIBRARY "PCSX2Lib"
EXPORTS

;    Init functions
    DetectCpuAndUserModeFunc
    AllocateCoreStuffsFunc
    ApplySettingsFunc

;    EE Core thread controls
    SysThreadBase_ResumeFunc
    SysThreadBase_SuspendFunc
    SysThreadBase_ResetFunc
    SysThreadBase_CancelFunc

    
;    MTGS thread controls
    MTGS_ResumeFunc
    MTGS_WaitForOpenFunc
    MTGS_IsSelfFunc
    MTGS_SuspendFunc
    MTGS_CancelFunc
    MTGS_FreezeFunc
    MTGS_WaitGSFunc
    
;    MTVU thread controls
    MTVU_CancelFunc
    vu1Thread_WaitVUFunc
    
;    Plugin management
    openPlugin_SPU2Func
    openPlugin_DEV9Func
    openPlugin_USBFunc
    openPlugin_FWFunc    
    setPluginsInitCallback
    setPluginsCloseCallback
    setPluginsShutdownCallback
    setPluginsOpenCallback
    setPluginsAreLoadedCallback
    resetCallbacksFunc
    setGS            
    setPAD            
    setSPU2            
    setCDVD    
    setMcd        
    setUSB            
    setFW            
    setDEV9        
    
;    Patches management
    setUI_EnableSysActionsCallback
    ForgetLoadedPatchesFunc
    inifile_commandFunc
    setLoadAllPatchesAndStuffCallback
    setSioSetGameSerialFunc
    getGameStartedFunc
    getGameLoadingFunc
    getElfCRCFunc
    VTLB_Alloc_PpmapFinc
    releaseWCHARStringFunc
    getSysGetBiosDiscIDFunc
    gsUpdateFrequencyCallFunc
    getSysGetDiscIDFunc
    
;    BIOS management
    setLoadBIOSCallbackCallback
    setCDVDNVMCallback
    setCDVDGetMechaVerCallback
    
;    Saving management
    getFreezeInternalsFunc
    getEmotionMemoryFunc
    getIopMemoryFunc
    getHwRegsFunc
    getIopHwRegsFunc
    getScratchpadFunc
    getVU0memFunc
    getVU1memFunc
    getVU0progFunc
    getVU1progFunc
    getFreezeOutFunc
    setDoFreezeCallback
    
;    Loading management
    setFreezeInFunc    
    setFreezeInternalsFunc
    setEmotionMemoryFunc
    setIopMemoryFunc
    setHwRegsFunc
    setIopHwRegsFunc
    setScratchpadFunc
    setVU0memFunc
    setVU1memFunc
    setVU0progFunc
    setVU1progFunc
    
;    Elf file management
    PCSX2_Hle_SetElfPathFunc

Init functions:

  • DetectCpuAndUserModeFunc - Function for detecting of the multimedia support of the CPU
  • AllocateCoreStuffsFunc - Function for allocating memory and initializing inner variables and translators
  • ApplySettingsFunc - Function for setting the new values for inner variables

EE Core thread controls:

  • SysThreadBase_ResumeFunc - Function for resuming EE Core thread (init state is not started and resume command starts this thread)
  • SysThreadBase_SuspendFunc - Function for suspending EE Core thread
  • SysThreadBase_ResetFunc - Function for stopping EE Core thread and releasing related memory
  • SysThreadBase_CancelFunc - Function for inactivating EE Core thread

MTGS thread controls:

  • MTGS_ResumeFunc - Function for resuming Graphics Synthesizer (GS) thread (init state is not started and resume command starts this thread)
  • MTGS_WaitForOpenFunc - Function for waiting of initializing of the graphic context of GS
  • MTGS_IsSelfFunc - Function for checking of the GS thread for preventing of mutex deadlock
  • MTGS_SuspendFunc - Function for suspending GS thread
  • MTGS_CancelFunc - Function for cancelling GS thread
  • MTGS_FreezeFunc - Function for saving of the graphic context from GS thread
  • MTGS_WaitGSFunc - Function for waiting to finish the current graphic context

MTVU thread controls:

  • MTVU_CancelFunc - Function for cancelling of the 3D Vector Unit Thread
  • vu1Thread_WaitVUFunc - Function for waiting of the starting of the 3D Vector Unit Thread

Plugin management:

  • openPlugin_SPU2Func - Function for opening AudioOutput context
  • openPlugin_DEV9Func - Function for opening DEV9 context
  • openPlugin_USBFunc - Function for opening USB context
  • openPlugin_FWFunc - Function for opening FW context
  • setPluginsInitCallback - Function for setting init callback C function for initializing from EE Core thread
  • setPluginsCloseCallback - Function for setting close callback C function for closing from EE Core thread
  • setPluginsShutdownCallback - Function for setting release callback C function for releasing plugins' resources from EE Core thread
  • setPluginsOpenCallback - Function for setting open callback C function for opening from EE Core thread
  • setPluginsAreLoadedCallback - Function for setting check loading status callback C function for checking status from EE Core thread
  • resetCallbacksFunc - Function for releasing all callback pointers
  • setGS - Function for setting of the C pointer on GS external module
  • setPAD - Function for setting of the C pointer on PAD external module
  • setSPU2 - Function for setting of the C pointer on AudioOutput external module
  • setCDVD - Function for setting of the C pointer on CDVD external module
  • setMcd - Function for setting of the C pointer on Memory Card external module
  • setUSB - Function for setting of the C pointer on USB external module
  • setFW - Function for setting of the C pointer on FW external module
  • setDEV9 - Function for setting of the C pointer on DEV9 external module

Patches management:

  • setUI_EnableSysActionsCallback - Function for setting UI update callback from EE Core thread
  • ForgetLoadedPatchesFunc - Function for releasing all current patches in EE Core
  • inifile_commandFunc - Function for settings text patches to EE Core
  • setLoadAllPatchesAndStuffCallback - Function for setting load patches callback from EE Core thread
  • setSioSetGameSerialFunc - Function for setting serial number of the game disk
  • getGameStartedFunc - Function for getting of EE Core gaming status
  • getGameLoadingFunc - Function for getting of EE Core game loading status
  • getElfCRCFunc - Function for getting of ElfFile CRC check sum
  • VTLB_Alloc_PpmapFinc - Function for reallocating memory for patches
  • releaseWCHARStringFunc - Function for releasing of the allocated memory for wchar_t string
  • getSysGetBiosDiscIDFunc - Function for getting of the Bios Disc ID
  • gsUpdateFrequencyCallFunc - Function for updating GS context after patching
  • getSysGetDiscIDFunc - Function for getting of the Disc ID

BIOS management:

  • setLoadBIOSCallbackCallback - Function for setting loading BIOS callback from EE Core thread.
  • setCDVDNVMCallback - Function for setting saving and loading BIOS Configuration callback from EE Core thread.
  • setCDVDGetMechaVerCallback - Function for setting loading DVD hardware serial number callback from EE Core thread.

Saving management:

  • getFreezeInternalsFunc - Function for getting internal variables as a byte array
  • getEmotionMemoryFunc - Function for getting EE Core memory as a byte array
  • getIopMemoryFunc - Function for getting I/O Processor memory as a byte array
  • getHwRegsFunc - Function for getting EE Core Hardware Registers as a byte array
  • getIopHwRegsFunc - Function for getting I/O Processor Hardware Registers as a byte array
  • getScratchpadFunc - Function for getting Scratchpad (Buffer) memory as a byte array
  • getVU0memFunc - Function for getting Vector Unit 0 memory as a byte array
  • getVU1memFunc - Function for getting Vector Unit 1 memory as a byte array
  • getVU0progFunc - Function for getting Vector Unit 0 program as a byte array
  • getVU1progFunc - Function for getting Vector Unit 1 program as a byte array
  • getFreezeOutFunc - Function for getting plugin memory as a byte array
  • setDoFreezeCallback - Function for setting saving plugin memory callback

Loading management:

  • setFreezeInFunc - Function for setting plugin memory as a byte array
  • setFreezeInternalsFunc - Function for setting internal variables as a byte array
  • setEmotionMemoryFunc - Function for setting EE Core memory as a byte array
  • setIopMemoryFunc - Function for setting I/O Processor memory as a byte array
  • setHwRegsFunc - Function for setting EE Core Hardware Registers as a byte array
  • setIopHwRegsFunc - Function for setting I/O Processor Hardware Registers as a byte array
  • setScratchpadFunc - Function for setting Scratchpad (Buffer) memory as a byte array
  • setVU0memFunc - Function for setting Vector Unit 0 memory as a byte array
  • setVU1memFunc - Function for setting Vector Unit 1 memory as a byte array
  • setVU0progFunc - Function for setting Vector Unit 0 program as a byte array
  • setVU1progFunc - Function for setting Vector Unit 1 program as a byte array

Elf file management:

  • PCSX2_Hle_SetElfPathFunc - Function for setting Elf file (unworkable, but it is needed for static linking)

These functions have specific orders of calling and external framework must execute them and invoke code in callback functions by specific algorithms.

In C# code, launching emulator begin from initializing:

C++
PCSX2LibNative.Instance.DetectCpuAndUserModeFunc();
PCSX2LibNative.Instance.AllocateCoreStuffsFunc
            (PCSX2Controller.Instance.m_Pcsx2Config.serialize());
PCSX2LibNative.Instance.PCSX2_Hle_SetElfPathFunc("");

Binding callback functions:

C++
private void Bind()
{
      foreach (var l_Module in ModuleManager.Instance.Modules)
      {
          PCSX2LibNative.Instance.setModule(l_Module);
      }

      PCSX2LibNative.Instance.setPluginsInitCallback = delegate()
      {
          ModuleControl.Instance.init();
      };

      PCSX2LibNative.Instance.setPluginsCloseCallback = delegate()
      {
          ModuleControl.Instance.close();
      };

      PCSX2LibNative.Instance.setPluginsShutdownCallback = delegate()
      {
          ModuleControl.Instance.shutdown();
      };

      PCSX2LibNative.Instance.setPluginsOpenCallback = delegate()
      {
          ModuleControl.Instance.open();
      };

      PCSX2LibNative.Instance.setPluginsAreLoadedCallback = delegate()
      {
          return ModuleControl.Instance.areLoaded();
      };
            
      PCSX2LibNative.Instance.setUI_EnableSysActionsCallback = delegate()
      {
          if (!PCSX2Controller.Instance.innerCall())
             LockScreenManager.Instance.hide();
      };

      PCSX2LibNative.Instance.setLoadAllPatchesAndStuffCallback = delegate(uint a_FirstArg)
      {
           PatchAndGameFixManager.Instance.LoadAllPatchesAndStuff();
      };

      PCSX2LibNative.Instance.setLoadBIOSCallbackCallback = 
                         delegate(IntPtr a_FirstArg, Int32 a_SecondArg)
      {
           Omega_Red.Tools.BiosControl.LoadBIOS(a_FirstArg, a_SecondArg);
      };

      PCSX2LibNative.Instance.setCDVDNVMCallback = 
                         delegate(IntPtr buffer, Int32 offset, Int32 bytes, Boolean read)
      {
          Omega_Red.Tools.BiosControl.NVMFile(buffer, offset, bytes, read);
      };

      PCSX2LibNative.Instance.setCDVDGetMechaVerCallback = delegate(IntPtr buffer)
      {
          Omega_Red.Tools.BiosControl.CDVDGetMechaVer(buffer);
      };

      PCSX2LibNative.Instance.setDoFreezeCallback = 
                         delegate(IntPtr a_FirstArg, Int32 a_mode, Int32 a_ModuleCode)
      {
          return ModuleControl.Instance.doFreeze(a_FirstArg, a_mode, a_ModuleCode);
      };
}

And resuming EE Core thread:

C++
PCSX2LibNative.Instance.SysThreadBase_ResumeFunc();

Omega Red project is complex and reviewing of the whole code needs ever a real book. However, I think that it can be important to pay attention to the architecture of the programing solutions.

Modules - Plugins

The original PCSX2 project defines a group of external plugins for interacting with emulator - video, audio, game pad, memory card. Omega Red project has the same solutions which are named modules - they DO NOT exist as real external files, but they are contained in execution file as resources. At the moment of launching of the application, they are unpacked, and at the moment of exit from the application, they are deleted. Another moment is defining module's interface - each module has its own set of functions which are used by PCSX2Lib, but for an external framework, it is useless - so, in this project, there is own common interface for interacting with modules:

C++
PCSX2_EXPORT_C_(void*) getAPI()
{
    return (void*)&CDVDapi_Iso;
}

PCSX2_EXPORT_C execute(const wchar_t* a_command, wchar_t** a_result)
{
    g_CDVD.execute(a_command, a_result);
}

PCSX2_EXPORT_C releaseString(wchar_t* a_string)
{
    if (a_string != nullptr)
        delete[] a_string;
}

Function getAPI returns pointer on PCSX2Lib API, function execute executes command from an external framework and returns result in the form of the XML document, function releaseString releases the returned result string memory.

Video Renderer

Omega Red has a module for rendering by DirectX11, but there is one problem - WPF supports only DirectX9 texture in D3DImage. This problem is resolved by the next way:

  1. Create DirectX texture with the "Shared" handle - Direct3D9Ex supports creating DirectX9 texture with DXGI shared handler.
  2. Create the shared DirectX11 texture from the DXGI shared handler of the DirectX9 texture:
C++
// Create shared texture
CComPtr<ID3D11Resource> l_Resource;
hr = m_dev->OpenSharedResource(sharedhandle, IID_PPV_ARGS(&l_Resource));
if (FAILED(hr)) return false;
hr = l_Resource->QueryInterface(IID_PPV_ARGS(&m_SharedTexture));

Touch Pad

Omega Red has an integrated touch pad:

Image 5

It is implemented according to the XInput specification by defining C# structures for copying button status and analog sticks axes into the native memory:

C#
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct XINPUT_GAMEPAD {
    public UInt16 wButtons;
  public byte bLeftTrigger;
  public byte bRightTrigger;
  public Int16 sThumbLX;
  public Int16 sThumbLY;
  public Int16 sThumbRX;
  public Int16 sThumbRY;
};

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct XINPUT_STATE {
    public UInt32 dwPacketNumber;
    public XINPUT_GAMEPAD Gamepad;
};

Screen and Video Capture

The original PCSX2 has some functionality for taking the rendered game image and record gameplay video, but such functionality is not easily accessible and is not optimized for such purpose. I decided to include more flexible solutions. It uses WPF functionality for capturing screen into the JPEG format image file by - it allows copy DirectX texture from back buffer to C# BitmapSource and encodes it using JpegBitmapEncoder:

C#
public byte[] takeScreenshot()
{            
    byte[] l_result = null;

    var l_D3D9Image = imageSource as D3D9Image;

    if(l_D3D9Image != null)
    {
        BitmapSource l_bitmap = l_D3D9Image.getBackBuffer();

        JpegBitmapEncoder l_encoder = new JpegBitmapEncoder();

        l_encoder.QualityLevel = 75;

        l_encoder.Frames.Add(BitmapFrame.Create(l_bitmap));

        using (var outputStream = new MemoryStream())
        {
            l_encoder.Save(outputStream);

            l_result = outputStream.ToArray();
        }
    }

    return l_result;
}

For capturing of gameplay video, I have used CaptureManager SDK - it is a simple SDK for capturing video and audio from many sources. For the purpose of this project, CaptureManager SDK has the following advantages:

  1. Simple and flexible C# interface - it allows to integrate video capture code to any WPF/C# project.
  2. Defining source by XML document - address of pointer on the capture DirectX11 texture is written as numbers in the text format:
XML
string lPresentationDescriptor = "<?xml version='1.0' encoding='UTF-8'?>" +
"<PresentationDescriptor StreamCount='1'>" +
    "<PresentationDescriptor.Attributes Title='Attributes of Presentation'>" +
        "<Attribute Name='MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK' 
        GUID='{58F0AAD8-22BF-4F8A-BB3D-D2C4978C6E2F}' Title='The symbolic link for a 
        video capture driver.' Description='Contains the unique symbolic link 
        for a video capture driver.'>" +
            "<SingleValue Value='ImageCaptureProcessor' />" +
        "</Attribute>" +
        "<Attribute Name='MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME' 
        GUID='{60D0E559-52F8-4FA2-BBCE-ACDB34A8EC01}' 
        Title='The display name for a device.' 
        Description='The display name is a human-readable string, 
        suitable for display in a user interface.'>" + 
            "<SingleValue Value='Image Capture Processor' />" +
        "</Attribute>" +
    "</PresentationDescriptor.Attributes>" + 
    "<StreamDescriptor Index='0' MajorType='MFMediaType_Video' 
    MajorTypeGUID='{73646976-0000-0010-8000-00AA00389B71}'>" + 
        "<MediaTypes TypeCount='1'>" + 
            "<MediaType Index='0'>" +
                "<MediaTypeItem Name='MF_MT_FRAME_RATE' 
                GUID='{C459A2E8-3D2C-4E44-B132-FEE5156C7BB0}' Title='Frame rate.' 
                Description='Frame rate of a video media type, in frames per second.'>" + 
                    "<RatioValue Value='30.0'>" + 
                        "<Value.ValueParts>" + 
                            "<ValuePart Title='Numerator'  Value='30' />" +  
                            "<ValuePart Title='Denominator'  Value='1' />" +  
                        "</Value.ValueParts>" + 
                    "</RatioValue>" + 
                "</MediaTypeItem>" +
                "<MediaTypeItem Name='CM_DirectX11_Capture_Texture' 
                GUID='{179B7A05-496A-4C9F-B8C6-15F04E669595}'>" +
                    "<SingleValue Value='{Temp_Capture_Texture}' />" +
                "</MediaTypeItem>" +
            "</MediaType>" +
        "</MediaTypes>" +
    "</StreamDescriptor>" +
"</PresentationDescriptor>";

where {Temp_Capture_Texture} is preplaced on text representation of pointer on DirectX11 render target texture which is used as source.

C#
lPresentationDescriptor = lPresentationDescriptor.Replace
("{Temp_Capture_Texture}", a_PtrDirectX11Source.ToInt32().ToString()); 

Audio stream is recorded by "Audio Loopback" - from inner system speaker output.

The CaptureManager SDK uses different video and audio encoders for recording of game play video.

Dependency

Omega Red is based on PCSX2 code and for correct linking of the original code at the process of compiling, it is placed in the root folder:

Image 6

The result binary executable file is placed into the "bin" folder:

Image 7

The source code of this project is stored in GitHub in Omega_Red repository: https://github.com/Xirexel/OmegaRed.

Finished Result

The result is presented in the form of the ONE executable file - it includes all needed code in form of the one file. So, the program is designed for "touch" control and it has the following features:

  1. Full screen size - program has only one window size - maximum which takes the whole screen area
  2. Minimum configuration - default configuration is enough for most games
  3. It allows only one player game configuration

The next sub sections describe the result program as more informative, but full screen images have poor quality in small HTML images.

User Interface

Omega Red is a project for making an original PCSX2 more friendly and easy using. These targets are reflected by design of the user interface with the features which can be got from WPF GUI framework.

Image 8

Original user interface of PCSX2 in "Win95" style:

Image 9

is replaced on the new style with "Touch - Tile" design for supporting of the screen touch controlling with minimum needs to use classic "mouse" HID:

Image 10

Resource Management

Much time had been spent on design of the simple schema for easy controlling and management of the main game playing resources: BIOSs, ISO game's discs, Memory cards, PADs, Savings.

BIOSs are important part of the working process of the emulator. Omega Red supports reading data from binary file or from ZIP archive:

Image 11

ISO disc image files are the only way for launching game on this emulator. These files are registered in collection of Game Discs and are recognized - the original PCSX2 emulator reads and checks ISO file at the time of launching of the game, but this new emulator checks type of image disc, supporting it by PS2, region of game disc without launching of emulator:

Image 12

Loading and saving states are significantly changed. The original PCSX2 emulator has limitation in 10-th file-slots on each game, WITHOUT defining date of saving and progress of gameplay:

Image 13

Omega Red allows create upto 100-th file-slots on each game at the game process. Each file-slot saves date of saving, duration of the current game session and captured image of the game process:

Image 14

In addition, at the moment of stopping of the emulator or at the moment of closing of Omega Red application, the current game process is saved into the special file "Autosave" - it allows to continue the game in case gamers forgot to save the last game session. Also, the sequence of loading the saved state has been changed - while the original PCSX2 needs load BIOS, load game disc, check it and only then it needs click on the needed slot, Omega Red loads the saved game state by one click. As a result, the time of loading of the saved game is decreased from 20 seconds to 3-5 seconds.

This project allows manage PS2 memory cards in a more "flexible" way:

Image 15

Memory cards can be created at gameplay time, and emulator can be switched from one memory card to another one at the gameplay for saving and loading data in games. Name of the created memory card files is based on name of the game and unique serial ID of the game disc - it allows display only "own" game memory card files.

PAD

Omega Red allows to switch game control from "Touch" PAD on "Game" Pad and back:

Image 16

Capture

Functionality for capturing of images and videos in the original PCSX2 has some limitation and it needs to do some research of configuration for finding these commands. In this project, I have redesigned it and have added the needed control buttons on the top of display:

Image 17

Quality of the captured image is fixed (75%). Quality of the "Live" gameplay video can be changed in range from 10% to 99%. Names of the created images and video files are generated by the friendly name of game and current date. The separated panel allows view captured images and videos at the pause time:

Image 18

Image 19

Image 20

General Config

"General config" panel allows to change non-game configurations: "Display mode", "Control mode", "Set Topmost", "Quality of video compression", "Turn off wide screen format", "Current language".

"Display mode" allows to switch displaying area from full screen to region and back.

Image 21

"Control mode" allows to switch general control from "Button" to "Touch" schema and back.

Image 22

"Set Topmost" sets application window on top other applications. "Quality of video compression" allows to set quality compression for video capturing functionality. "Turn off wide screen format" - by default, Omega Red sets available patches for changing proportion of screen to 16/9, but this option allows to disable these patches. "Current language:" allows to change current language.

"Current colour schema:" allows to change current colour schema.

Image 23

"Touch pad scale" allows change scale of the game touch pad elements for suitable size of the screen and size of fingers.

162% of the touch pad scale:

Image 24

78% of the touch pad scale:

Image 25

Tessellation

Omega Red uses DirectX 11 for rendering of emulated game. This technology supports many techniques of the modern graphic cards. One of them is Tessellation - a special technique for uprising quality of the meshes at runtime.

Image 26

I have included tessellation into the Omega Red by adding special config Rendering schema:

Image 27

The result has the next results:

DEFAULT

Image 28

TESSELLATED

Image 29

DEFAULT

Image 30

TESSELLATED

Image 31

FXAA

This options Enable FXAA allows turn on or off anti-aliasing postprocessing:

Image 32

Image 33

Quick Saving

Omega Red supports saving and loading of the current game state. I have improved it by adding quick saving and loading commands:

Image 34

Omega Red has 5 quick saving slots with queued order - the most new saving is placed in front of the queue and the oldest saving is placed in the tail of the queue.

Additional functionality of the quick saving is extended by physical game pad - quick saving and quick LOADING by the special combinations of buttons of the physical game pad:

Quick saving: Start + Left Shoulder

Image 35

Quick loading: Start + Right Shoulder

Image 36

Quick loading has "30 seconds rule" - it means if time the next quick loading is less 30 seconds after the last one then Omega Red will load the previous quick saving slot. As a result, it is possible to review all current quick savings for searching the suitable one by clicking combination Start + Right Shoulder again and again!

Audio Volume Control

Omega Red supports control of the rendered audio volume by special slider volume and mute button:

Image 37

This component controls audio volume only in context of the local audio renderer WITHOUT changing of output speakers volume!

Off Screen Mode

Omega Red has a function for rendering of the gaming video and audio on the main desktop screen of personal computer. It is a normal mode of this PS2 emulator. However, after some research, I have decided to improve an architect of the emulator - add the new functionality for remote displaying of the rendered game on the remote devices as Android TV via LAN by RTSP protocol. For preventing of potential problems with using of personal computer with different tasks, I have added to Omega Red a special mode: "Off screen" which is enabled by argument command /OffScreen . This mode redirects video and audio rendered outputs from the current user context into the RTSP server inputs - as a result, on the local personal computer, Omega Red PS2 emulator is launched in hidden state with control icons. PS2 game images can be launched from taskbar icon. Gameplay control is managed by physical game pad.

Fast Loading Icon

Omega Red keeps the reference on the last selected game disk and selects it in the next application session - there is high probability for continuing of the last game in the last saving - Autosaving. Displaying the icon of the autosaving allows to continue game by ONE click on this icon.

Image 38

PSP Emulator

About half year ago, I got reference on "Valkyria Chronicles 4" in Steam. I have been puzzled about "4" number - I played in "Valkyria Chronicles" long time ago. However, what about "Valkyria Chronicles 2" and "Valkyria Chronicles 3"? Those games were published on game consoles. The most accessible for me is PSP version via PPSSPP - but I have done not like touch control of that emulator. Moreover, I would not like to have TWO different programs for play games and switch from one to another. So, I have an idea - add PPSSPP emulator into the Omega Red and create PLATFORM for the PS2 and PSP games! I tried and it is workable:

GoogleDrive and YouTube

After some time of research, I have decided to add Google account "binding" - it allows to include some functionality of the Google service: GoogleDrive and YouTube - storing game savings in the "Cloud" and easy uploading recorded video on your YouTube account.

Image 39

After clicking on the Google icon, the application will open your Google account in the current default Internet browser for "binding" Omega Red with your Google account:

Image 40

After "binding", all savings will have got GoogleDrive icon for marking "cloud" saving access:

Image 41

Also there is access to download savings from GoogleDrive on your computer:

Image 42

After "binding" with YouTube account, the special YouTube icon will be displayed in Omega Red video player for directly uploading the current video on your account:

Image 43

Game Play Streaming (YouTube, Facebook, Twitch)

Yes, it is a real mad idea - add live video and audio game play streaming into the PS2/PSP emulator.

This task is interesting by the next aspects: inner capture video and audio. The regular streaming application usually captures video from screen and audio from audio speaker. However, I have decided to change conception - add streaming functionality on the level of the emulator for ISOLATION of the video and audio from context of the Windows OS system mixers.

Streaming functionality has two parts:

  • Configuration video and audio encoding, and selection of the Internet streaming services for live broadcasting
  • Configuration of mixers - mixing live game play video and audio with additional sources: microphone, webcam, JPG/PNG/GIF(animated) files

Configuration video and audio encoding:

Image 44

Configuration of streaming has begun from selection of the capture mode Streaming. This mode allows select video and audio bitrates of the streaming. Also, it is possible to select or TYPE address of the target streaming service.

It is important to mark that Omega Red supports open and ENCRYPTED (SSL) connection!

Streaming service of Facebook has published the next announcement:

«As announced last April, all live video uploads will be required to use RTMPS (RTMP over a TLS/SSL connection) by May 1, 2019, and it's important that developers take the time to ensure that their integration is compliant before this date.

We're committed to protecting the integrity of the Facebook platform, and as part of this work, we're requiring that live video uploads use RTMPS as it provides a greater level of security for the video content».

I had decided that supporting of the RTMPS is very perspective and spent some time on adding OpenSSL to RTMP library. It is WORKABLE!!! Facebook receives streaming on the encrypted connection!

Streaming has begun from pressing on icon Record/Streaming:

Image 45

Configuration of mixers have become available AFTER staring of the recording/streaming:

Image 46

Media sources has become available in Media panel - this expander menu includes video and audio sources for mixing. In addition, it is possible add JPG/PNG/GIF(animated) files for mixing.

For microphones, it is possible to control proportion of the audio mixing. Selection of the microphone is executed by click on check button, mixing is controlled by Volume slider.

Image 47

Selection of the webcam is executed by click on check button, resolution of the webcam video is selected by click on combo menu.

Image 48

Opacity of mixing can be controlled by Opacity slider.

Image 49

Position and size of the mixed video stream can be changed at streaming time:

Image 50

My test streaming:

 

PS1 Emulator

After some time of thinking I have decided to add in my project emulator of the first game console of PlayStation line. However, I have faced with problem with stop supporting of the PCSX-Reloaded open source by community - code is stopped supporting about 15-20 years ago, and there is a problem to integrate graphic renderer on base DirectDraw with WPF and DirectX 11 texhnology. I have decided to bind the software renderer of PCSX-Reloaded with WPF by coping rendered video from system memory to video memory by fast coping of DirectX 11 texture. This solution is not effective, but it allows get 100% compatibility and is suitable for the first release.     

In addition, I have added two features for compatibility with PCSX-Reloaded:

  1. Visual vibration - game pad of PlayStations has feature of feed back which allows to more deep integrate gamer with gameplay. Omega Red project supports feed back for game pad control, but feed back from touch pad is fantastic feature of PlayStation 6:)) However, at time of research code of PCSX-Reloaded I had found reference on callback function from emulator of game pad to graphic renderer! I have found that idea to react on vibration of game pad by transformation of the rendered image is GREAT! As a result, I have added this features in my project:                                                                                     Image 51 Image 52
  2. Memory card shared - original Omega Red project creates memory card for each game on base of the unique serial number of game disc for preventing of overwriting savings of one game by another. This schema is workable for PlayStation 2 because game is usually takes one DVD, but in case of PlayStation 1 games there is a problem with transfer game state from one game disc to another - many games on PlayStation 1 takes two or more disks. As result, I have decided add one shared memory cred for all PlayStation 1 games.                                                                                                        Image 53

In addition, I have added three new features:

  1. Selection constant bitrate for video encoding of the live game process:                                                             Image 54        Selection size of the target recorded file:                                                                                                                   Image 55
  2. Splitting BIOSs and game Discs by groups for PlayStation 1, PlayStation 2 and PlayStation Portable:                Image 56
  3. Display names of the current BIOS and game disc in head of the releated sections:                                              Image 57

Demonstration of games on all three platforms you can see in the next demo:

 

New PS1 graphic renderer

After some time of testing PS1 code I have found that software renderer has limitation - while I had tried to expand the result image from TV resolution on HD ready 720p I found that its image contained BIG pixels artifacts of polygons and textures. The suitable solution is to replace software renderer on hardware one. However, I have found that the current solutions of hardware renderer for PS1 use OpenGL driver - it is a problem for my project Omega Red because it is based on WPF, DirectX9 and DIrectX11. I had found only one solution - write the new graphic renderer on DirectX11 !!!

The result of my work is good and very perspective:

Demonstration of comparison these renderers you can see in the next demo:

 

Refresh frame rate

This project uses WPF C# framework for intermediate layer between render of emulator and graphic context of display: render draws scene into the texture and WPF framework embed this texture into the user interface. Embedding of DirectX texture into the user interface is 'bottleneck' of WPF graphic driver - WPF was designed for Windows XP SP2 and has in basement DirectX9 layer, embedding DirectX9 texture uses CPU power. 

As a result, loading of CPU is increased and latency of CPU is increased too - in audio stream of emulator become silence pauses. Decrease of CPU loading is possible by skipping of DirectX9 texture embedding. The current frequency of texture updating is possible to monitore by option "Show frames per second":

Image 58

Frame updating is possible change by option "Skip frame mode:":

Image 59

 

4K (2160p) resolution for PS1, PS2, PSP games

Most emulators have software solution for rendering game scence by native APIs: DirectX or OpenGL. As a result, emulators have graphic engine with the different functionality. One of them is rendering with the target output window resolution. This solution uses special target video texture as the target rendering destination for PS1, PS2, PSP emulators, and size of this texture defines view size of the virtual camera.  

The size of target rendering texture is defined in config size:

Image 60

Quality of rendering with 720р / 2160р can be compared in video:

Resume

Omega Red has been developed since a simple idea to improve the original PCSX2 emulator and add some new features. It is a more user friendly solution and can be useful for PCSX2 development society.

Points of Interest

At the time of development of the C# part of the project, I was faced with the problem of stack overflow - at the moment of the processing of data from DVD image program, throw out exception of stack overflow type. After some research, I found that the original PCSX2 project generates code of MIPS translators by combination of C/C++ macros. It allows fast generation of effective code, but this code has a recursive structure which consumes STACK of process. For native C/C++, it is not a problem, but C# projects has a limited size of STACK which IS NOT enough for PCSX2 code. How has it been resolved? - it is very easy. There is a special program "editbin.exe" in Visual Studio pack which allows to edit the compiled program - argument "/STACK:" allows to change STACK of program process. Next command is executed in "Post-build event command line":

"$(DevEnvDir)..\..\VC\bin\editbin.exe" /STACK:6000000 "$(TargetPath)"

It expands STACK of C# program up to 6 million bytes.

History and Updates

09/10/2018: First update

  • Added "Current colour schema:" option for changing of the colour of application's elements

19/11/2018: Second update

  • Migrated Omega Red Visual Studio project from VS2013 to VS2017 with supporting the last updates of GSdx in the VideoRenderer project.
  • Added "Touch pad scale" option for changing of the game touch pad elements for suitable size of the screen and size of fingers.
  • Added MediaStream project for implementing of the RTSP Server of the "Live" streaming functionality of the current game.

11/02/2019: Third update

  • Added "Tessellation" config.
  • Added "Audio volume control" component.
  • Added "Quick saving" component.
  • Added remote displaying via RTSP Server supporting.

02/04/2019: Fourth update

  • Added "Enable FXAA" for PCSX2
  • Added "Fast loading icon"
  • Added PPSSPP emulator

27/06/2019: Fifth update

  • Added GoogleDrive and YouTube supporting
  • Added game play streaming functionality

25/11/2019: Sixth update

  • Added PCSX-Reloaded emulator of PlayStation 1
  • Added "Visual vibration is enabled"
  • Added shared memory card
  • Added selection video encoder bitrate
  • Added selection size of recorded file
  • Added grouping of BIOSs and game discs
  • Added displaing names of the current BIOS and game disc in head of the releated sections

21/01/2020: Seventh update

  • Replace software renderer on DirectX 11 renderer in emulator of PlayStation 1.

13/07/2020: Eightth update

03/08/2020: Nineth update

  • Added choice rendering resolutions: 710p, 1080p, 1440p, 2160p

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMessage Removed Pin
24-Nov-19 21:31
Geca24-Nov-19 21:31 
QuestionVirus warning Pin
wvd_vegt9-Oct-18 3:17
professionalwvd_vegt9-Oct-18 3:17 
FYI Get a virus warning on the zipped exe file.
wvd_vegt

AnswerRe: Virus warning Pin
Evgeny Pereguda9-Oct-18 13:21
Evgeny Pereguda9-Oct-18 13:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.