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
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.
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:
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).
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.
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.
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.
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.
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:
PCSX2LibNative.Instance.DetectCpuAndUserModeFunc();
PCSX2LibNative.Instance.AllocateCoreStuffsFunc
(PCSX2Controller.Instance.m_Pcsx2Config.serialize());
PCSX2LibNative.Instance.PCSX2_Hle_SetElfPathFunc("");
Binding callback functions:
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:
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.
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:
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.
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:
- Create DirectX texture with the "
Shared
" handle - Direct3D9Ex
supports creating DirectX9 texture with DXGI shared handler. - Create the shared DirectX11 texture from the DXGI shared handler of the DirectX9 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));
Omega Red has an integrated touch pad:
It is implemented according to the XInput
specification by defining C# structures for copying button status and analog sticks axes into the native memory:
[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;
};
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
:
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:
- Simple and flexible C#
interface
- it allows to integrate video capture code to any WPF/C# project. - Defining source by XML document - address of pointer on the capture DirectX11 texture is written as numbers in the text format:
string lPresentationDescriptor = "='1.0'='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.
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.
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:
The result binary executable file is placed into the "bin" folder:
The source code of this project is stored in GitHub in Omega_Red
repository: https://github.com/Xirexel/OmegaRed.
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:
- Full screen size - program has only one window size - maximum which takes the whole screen area
- Minimum configuration - default configuration is enough for most games
- 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.
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.
Original user interface of PCSX2 in "Win95" style:
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:
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:
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:
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:
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:
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:
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.
Omega Red allows to switch game control from "Touch" PAD on "Game" Pad and back:
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:
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:
"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.
"Control mode" allows to switch general control from "Button" to "Touch" schema and back.
"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.
"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:
78% of the touch pad scale:
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.
I have included tessellation into the Omega Red by adding special config Rendering schema:
The result has the next results:
DEFAULT
TESSELLATED
DEFAULT
TESSELLATED
This options Enable FXAA allows turn on or off anti-aliasing postprocessing:
Omega Red supports saving and loading of the current game state. I have improved it by adding quick saving and loading commands:
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
Quick loading: Start + Right Shoulder
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!
Omega Red supports control of the rendered audio volume by special slider volume and mute button:
This component controls audio volume only in context of the local audio renderer WITHOUT changing of output speakers volume!
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.
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.
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:
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.
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:
After "binding", all savings will have got GoogleDrive icon for marking "cloud" saving access:
Also there is access to download savings from GoogleDrive on your computer:
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:
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:
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
:
Configuration of mixers have become available AFTER staring of the recording/streaming:
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.
Selection of the webcam is executed by click on check button, resolution of the webcam video is selected by click on combo menu.
Opacity of mixing can be controlled by Opacity slider.
Position and size of the mixed video stream can be changed at streaming time:
My test streaming:
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:
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: 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.
In addition, I have added three new features:
- Selection constant bitrate for video encoding of the live game process: Selection size of the target recorded file:
- Splitting BIOSs and game Discs by groups for PlayStation 1, PlayStation 2 and PlayStation Portable:
- Display names of the current BIOS and game disc in head of the releated sections:
Demonstration of games on all three platforms you can see in the next demo:
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:
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
":
Frame updating is possible change by option "Skip frame mode:
":
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:
Quality of rendering with 720р / 2160р can be compared in video:
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.
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.
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