View | Details | Raw Unified | Return to bug 252191
Collapse All | Expand All

(-)b/emulators/libretro-pcsx2/Makefile (+65 lines)
Added Link Here
1
# $FreeBSD$
2
3
PORTNAME=	libretro-pcsx2
4
PORTVERSION=	0.20201030
5
CATEGORIES=	emulators games
6
7
MAINTAINER=	beyert@cs.ucr.edu
8
COMMENT=	Standalone port of pcsx2 to libretro
9
10
LICENSE=	GPLv3
11
LICENSE_FILE=	${WRKSRC}/COPYING.GPLv3
12
13
ONLY_FOR_ARCHS=>i386 amd64
14
15
LIB_DEPENDS=	libpng16.so:graphics/png \
16
	libcdio.so:sysutils/libcdio \
17
	libportaudio.so:audio/portaudio \
18
	libSoundTouch.so:audio/soundtouch \
19
	libharfbuzz.so:print/harfbuzz
20
21
USES=		compiler:c++11-lib cmake
22
23
CPPFLAGS+=	-I${LOCALBASE}/include/wx-3.0
24
USE_CXXSTD=	c++11
25
#LDFLAGS+=	-L${LOCALBASE}/lib -I/usr/lib
26
USE_LDCONFIG=	yes
27
CMAKE_CPP_FLAGS=	${CPPFLAGS}
28
CMAKE_PREFIX_PATH=	${LOCALBASE}/include/wx-3.0
29
CMAKE_C_FLAGS=	${CFLAGS}
30
CMAKE_CXX_FLAGS=	${CFLAGS}
31
CMAKE_ARGS+=	-DLIBRETRO=yes
32
CMAKE_ARGS+=	-DwxWidgets_INCLUDE_DIRS="${LOCALBASE}/include/wx-3.0"
33
CMAKE_ARGS+=	-Dgtk_INCLUDE_DIR="${LOCALBASE}/include/gtk-3.0"
34
35
# lib depends on devel/ccache
36
WITH_CCACHE_BUILD=	yes
37
38
HAVE_GTK3=	true
39
#USES=		gnome xorg gl sdl dos2unix cmake:insource iconv gettext linux:c7 pkgconfig
40
#USE_LINUX=	libaio
41
USE_WX=		3.0+
42
#USE_XORG=	ice x11 xv xext xxf86vm xtst xrandr xi
43
USE_GL=	gl glew glu
44
USE_GNOME=	glib20
45
#USE_SDL=	sdl2
46
47
MAKE_JOBS_UNSAFE=	yes
48
49
USE_GITHUB=	yes
50
GH_ACCOUNT=	libretro
51
GH_PROJECT=	pcsx2
52
GH_TAGNAME=	1251fa4
53
54
PLIST_FILES=	lib/libretro/pcsx2_libretro.so
55
56
post-patch:
57
	${CP} files/3rdparty_wxwidgets3.0_src_unix_fswatcher__kqueue.cpp \
58
		${WRKSRC}/3rdparty/wxwidgets3.0/src/unix/fswatcher_kqueue.cpp
59
60
do-install:
61
	${MKDIR} ${STAGEDIR}/${PREFIX}/lib/libretro;
62
	${INSTALL_LIB} ${WRKDIR}/.build/pcsx2/pcsx2_libretro.so \
63
		${STAGEDIR}/${PREFIX}/lib/libretro;
64
65
.include <bsd.port.mk>
(-)b/emulators/libretro-pcsx2/distinfo (+3 lines)
Added Link Here
1
TIMESTAMP = 1604098409
2
SHA256 (libretro-pcsx2-0.20201030-1251fa4_GH0.tar.gz) = 01b329b4bba210022f0f0f889b2e4722ef530b766eaf7036194a53668b47a245
3
SIZE (libretro-pcsx2-0.20201030-1251fa4_GH0.tar.gz) = 15636747
(-)b/emulators/libretro-pcsx2/files/3rdparty_wxwidgets3.0_src_unix_fswatcher__kqueue.cpp (+459 lines)
Added Link Here
1
/////////////////////////////////////////////////////////////////////////////
2
// Name:        src/unix/fswatcher_kqueue.cpp
3
// Purpose:     kqueue-based wxFileSystemWatcher implementation
4
// Author:      Bartosz Bekier
5
// Created:     2009-05-26
6
// Copyright:   (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
7
// Licence:     wxWindows licence
8
/////////////////////////////////////////////////////////////////////////////
9
10
// For compilers that support precompilation, includes "wx.h".
11
#include "wx/wxprec.h"
12
13
#ifdef __BORLANDC__
14
    #pragma hdrstop
15
#endif
16
17
#if wxUSE_FSWATCHER
18
19
#include "wx/fswatcher.h"
20
21
#ifdef wxHAS_KQUEUE
22
23
#include <inttypes.h>
24
#include <sys/types.h>
25
#include <sys/event.h>
26
#include <sys/param.h>
27
28
#include "wx/dynarray.h"
29
#include "wx/evtloop.h"
30
#include "wx/evtloopsrc.h"
31
32
#include "wx/private/fswatcher.h"
33
34
namespace
35
{
36
37
// NetBSD is different as it uses intptr_t as type of kevent struct udata field
38
// for some reason, instead of "void*" as all the other platforms using kqueue.
39
#ifdef __NetBSD__
40
    inline intptr_t ToUdata(void* d) { return reinterpret_cast<intptr_t>(d); }
41
    inline void* FromUdata(intptr_t d) { return reinterpret_cast<void*>(d); }
42
#else
43
    inline void* ToUdata(void* d) { return d; }
44
    inline void* FromUdata(void* d) { return d; }
45
#endif
46
47
} // anonymous namespace
48
49
// ============================================================================
50
// wxFSWSourceHandler helper class
51
// ============================================================================
52
53
class wxFSWatcherImplKqueue;
54
55
/**
56
 * Handler for handling i/o from inotify descriptor
57
 */
58
class wxFSWSourceHandler : public wxEventLoopSourceHandler
59
{
60
public:
61
    wxFSWSourceHandler(wxFSWatcherImplKqueue* service) :
62
        m_service(service)
63
    {  }
64
65
    virtual void OnReadWaiting();
66
    virtual void OnWriteWaiting();
67
    virtual void OnExceptionWaiting();
68
69
protected:
70
    wxFSWatcherImplKqueue* m_service;
71
};
72
73
// ============================================================================
74
// wxFSWatcherImpl implementation & helper wxFSWSourceHandler implementation
75
// ============================================================================
76
77
/**
78
 * Helper class encapsulating inotify mechanism
79
 */
80
class wxFSWatcherImplKqueue : public wxFSWatcherImpl
81
{
82
public:
83
    wxFSWatcherImplKqueue(wxFileSystemWatcherBase* watcher) :
84
        wxFSWatcherImpl(watcher),
85
        m_source(NULL),
86
        m_kfd(-1)
87
    {
88
        m_handler = new wxFSWSourceHandler(this);
89
    }
90
91
    virtual ~wxFSWatcherImplKqueue()
92
    {
93
        // we close kqueue only if initialized before
94
        if (IsOk())
95
        {
96
            Close();
97
        }
98
99
        delete m_handler;
100
    }
101
102
    bool Init()
103
    {
104
        wxCHECK_MSG( !IsOk(), false,
105
                     "Kqueue appears to be already initialized" );
106
107
        wxEventLoopBase *loop = wxEventLoopBase::GetActive();
108
        wxCHECK_MSG( loop, false, "File system watcher needs an active loop" );
109
110
        // create kqueue
111
        m_kfd = kqueue();
112
        if (m_kfd == -1)
113
        {
114
            wxLogSysError(_("Unable to create kqueue instance"));
115
            return false;
116
        }
117
118
        // create source
119
        m_source = loop->AddSourceForFD(m_kfd, m_handler, wxEVENT_SOURCE_INPUT);
120
121
        return m_source != NULL;
122
    }
123
124
    void Close()
125
    {
126
        wxCHECK_RET( IsOk(),
127
                    "Kqueue not initialized or invalid kqueue descriptor" );
128
129
        if ( close(m_kfd) != 0 )
130
        {
131
            wxLogSysError(_("Error closing kqueue instance"));
132
        }
133
134
        wxDELETE(m_source);
135
    }
136
137
    virtual bool DoAdd(wxSharedPtr<wxFSWatchEntryKq> watch)
138
    {
139
        wxCHECK_MSG( IsOk(), false,
140
                    "Kqueue not initialized or invalid kqueue descriptor" );
141
142
        struct kevent event;
143
        int action = EV_ADD | EV_ENABLE | EV_CLEAR | EV_ERROR;
144
        int flags = Watcher2NativeFlags(watch->GetFlags());
145
        EV_SET( &event, watch->GetFileDescriptor(), EVFILT_VNODE, action,
146
                flags, 0, ToUdata(watch.get()) );
147
148
        // TODO more error conditions according to man
149
        // TODO best deal with the error here
150
        int ret = kevent(m_kfd, &event, 1, NULL, 0, NULL);
151
        if (ret == -1)
152
        {
153
            wxLogSysError(_("Unable to add kqueue watch"));
154
            return false;
155
        }
156
157
        return true;
158
    }
159
160
    virtual bool DoRemove(wxSharedPtr<wxFSWatchEntryKq> watch)
161
    {
162
        wxCHECK_MSG( IsOk(), false,
163
                    "Kqueue not initialized or invalid kqueue descriptor" );
164
165
        // TODO more error conditions according to man
166
        // XXX closing file descriptor removes the watch. The logic resides in
167
        // the watch which is not nice, but effective and simple
168
        if ( !watch->Close() )
169
        {
170
            wxLogSysError(_("Unable to remove kqueue watch"));
171
            return false;
172
        }
173
174
        return true;
175
    }
176
177
    virtual bool RemoveAll()
178
    {
179
        wxFSWatchEntries::iterator it = m_watches.begin();
180
        for ( ; it != m_watches.end(); ++it )
181
        {
182
            (void) DoRemove(it->second);
183
        }
184
        m_watches.clear();
185
        return true;
186
    }
187
188
    // return true if there was no error, false on error
189
    bool ReadEvents()
190
    {
191
        wxCHECK_MSG( IsOk(), false,
192
                    "Kqueue not initialized or invalid kqueue descriptor" );
193
194
        // read events
195
        do
196
        {
197
            struct kevent event;
198
            struct timespec timeout = {0, 0};
199
            int ret = kevent(m_kfd, NULL, 0, &event, 1, &timeout);
200
            if (ret == -1)
201
            {
202
                wxLogSysError(_("Unable to get events from kqueue"));
203
                return false;
204
            }
205
            else if (ret == 0)
206
            {
207
                return true;
208
            }
209
210
            // we have event, so process it
211
            ProcessNativeEvent(event);
212
        }
213
        while (true);
214
215
        // when ret>0 we still have events, when ret<=0 we return
216
        wxFAIL_MSG( "Never reached" );
217
        return true;
218
    }
219
220
    bool IsOk() const
221
    {
222
        return m_source != NULL;
223
    }
224
225
protected:
226
    // returns all new dirs/files present in the immediate level of the dir
227
    // pointed by watch.GetPath(). "new" means created between the last time
228
    // the state of watch was computed and now
229
    void FindChanges(wxFSWatchEntryKq& watch,
230
                     wxArrayString& changedFiles,
231
                     wxArrayInt& changedFlags)
232
    {
233
        wxFSWatchEntryKq::wxDirState old = watch.GetLastState();
234
        watch.RefreshState();
235
        wxFSWatchEntryKq::wxDirState curr = watch.GetLastState();
236
237
        // iterate over old/curr file lists and compute changes
238
        wxArrayString::iterator oit = old.files.begin();
239
        wxArrayString::iterator cit = curr.files.begin();
240
        for ( ; oit != old.files.end() && cit != curr.files.end(); )
241
        {
242
            if ( *cit == *oit )
243
            {
244
                ++cit;
245
                ++oit;
246
            }
247
            else if ( *cit <= *oit )
248
            {
249
                changedFiles.push_back(*cit);
250
                changedFlags.push_back(wxFSW_EVENT_CREATE);
251
                ++cit;
252
            }
253
            else // ( *cit > *oit )
254
            {
255
                changedFiles.push_back(*oit);
256
                changedFlags.push_back(wxFSW_EVENT_DELETE);
257
                ++oit;
258
            }
259
        }
260
261
        // border conditions
262
        if ( oit == old.files.end() )
263
        {
264
            for ( ; cit != curr.files.end(); ++cit )
265
            {
266
                changedFiles.push_back( *cit );
267
                changedFlags.push_back(wxFSW_EVENT_CREATE);
268
            }
269
        }
270
        else if ( cit == curr.files.end() )
271
        {
272
            for ( ; oit != old.files.end(); ++oit )
273
            {
274
                changedFiles.push_back( *oit );
275
                changedFlags.push_back(wxFSW_EVENT_DELETE);
276
            }
277
        }
278
279
        wxASSERT( changedFiles.size() == changedFlags.size() );
280
281
#if 0
282
        wxLogTrace(wxTRACE_FSWATCHER, "Changed files:");
283
        wxArrayString::iterator it = changedFiles.begin();
284
        wxArrayInt::iterator it2 = changedFlags.begin();
285
        for ( ; it != changedFiles.end(); ++it, ++it2)
286
        {
287
            wxString action = (*it2 == wxFSW_EVENT_CREATE) ?
288
                                "created" : "deleted";
289
            wxLogTrace(wxTRACE_FSWATCHER, wxString::Format("File: '%s' %s",
290
                        *it, action));
291
        }
292
#endif
293
    }
294
295
    void ProcessNativeEvent(const struct kevent& e)
296
    {
297
        void* const udata = FromUdata(e.udata);
298
299
        wxASSERT_MSG(udata, "Null user data associated with kevent!");
300
        wxLogTrace(wxTRACE_FSWATCHER, "Event: ident=%" PRIuPTR ", filter=%hd, flags=%hu, "
301
#if __FreeBSD_version >= 1200033
302
                   "fflags=%u, data=%" PRId64 ", user_data=%p",
303
#else
304
                   "fflags=%u, data=%" PRIdPTR ", user_data=%p",
305
#endif
306
                   e.ident, e.filter, e.flags, e.fflags, e.data, udata);
307
308
        // for ease of use
309
        wxFSWatchEntryKq& w = *(static_cast<wxFSWatchEntry*>(udata));
310
        int nflags = e.fflags;
311
312
        // clear ignored flags
313
        nflags &= ~NOTE_REVOKE;
314
315
        // TODO ignore events we didn't ask for + refactor this cascade ifs
316
        // check for events
317
        while ( nflags )
318
        {
319
            // when monitoring dir, this means create/delete
320
            const wxString basepath = w.GetPath();
321
            if ( nflags & NOTE_WRITE && wxDirExists(basepath) )
322
            {
323
                // NOTE_LINK is set when the dir was created, but we
324
                // don't care - we look for new names in directory
325
                // regardless of type. Also, clear all this, because
326
                // it cannot mean more by itself
327
                nflags &= ~(NOTE_WRITE | NOTE_ATTRIB | NOTE_LINK);
328
329
                wxArrayString changedFiles;
330
                wxArrayInt changedFlags;
331
                FindChanges(w, changedFiles, changedFlags);
332
333
                wxArrayString::iterator it = changedFiles.begin();
334
                wxArrayInt::iterator changeType = changedFlags.begin();
335
                for ( ; it != changedFiles.end(); ++it, ++changeType )
336
                {
337
                    const wxString fullpath = w.GetPath() +
338
                                                wxFileName::GetPathSeparator() +
339
                                                  *it;
340
                    const wxFileName path(wxDirExists(fullpath)
341
                                            ? wxFileName::DirName(fullpath)
342
                                            : wxFileName::FileName(fullpath));
343
344
                    wxFileSystemWatcherEvent event(*changeType, path, path);
345
                    SendEvent(event);
346
                }
347
            }
348
            else if ( nflags & NOTE_RENAME )
349
            {
350
                // CHECK it'd be only possible to detect name if we had
351
                // parent files listing which we could confront with now and
352
                // still we couldn't be sure we have the right name...
353
                nflags &= ~NOTE_RENAME;
354
                wxFileSystemWatcherEvent event(wxFSW_EVENT_RENAME,
355
                                        basepath, wxFileName());
356
                SendEvent(event);
357
            }
358
            else if ( nflags & NOTE_WRITE || nflags & NOTE_EXTEND )
359
            {
360
                nflags &= ~(NOTE_WRITE | NOTE_EXTEND);
361
                wxFileSystemWatcherEvent event(wxFSW_EVENT_MODIFY,
362
                                        basepath, basepath);
363
                SendEvent(event);
364
            }
365
            else if ( nflags & NOTE_DELETE )
366
            {
367
                nflags &= ~(NOTE_DELETE);
368
                wxFileSystemWatcherEvent event(wxFSW_EVENT_DELETE,
369
                                        basepath, basepath);
370
                SendEvent(event);
371
            }
372
            else if ( nflags & NOTE_ATTRIB )
373
            {
374
                nflags &= ~(NOTE_ATTRIB);
375
                wxFileSystemWatcherEvent event(wxFSW_EVENT_ACCESS,
376
                                        basepath, basepath);
377
                SendEvent(event);
378
            }
379
380
            // clear any flags that won't mean anything by themselves
381
            nflags &= ~(NOTE_LINK);
382
        }
383
    }
384
385
    void SendEvent(wxFileSystemWatcherEvent& evt)
386
    {
387
        m_watcher->GetOwner()->ProcessEvent(evt);
388
    }
389
390
    static int Watcher2NativeFlags(int WXUNUSED(flags))
391
    {
392
        // TODO: it would be better to only subscribe to what we need
393
        return NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND |
394
               NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME |
395
               NOTE_REVOKE;
396
    }
397
398
    wxFSWSourceHandler* m_handler;        // handler for kqueue event source
399
    wxEventLoopSource* m_source;          // our event loop source
400
401
    // descriptor created by kqueue()
402
    int m_kfd;
403
};
404
405
406
// once we get signaled to read, actuall event reading occurs
407
void wxFSWSourceHandler::OnReadWaiting()
408
{
409
    wxLogTrace(wxTRACE_FSWATCHER, "--- OnReadWaiting ---");
410
    m_service->ReadEvents();
411
}
412
413
void wxFSWSourceHandler::OnWriteWaiting()
414
{
415
    wxFAIL_MSG("We never write to kqueue descriptor.");
416
}
417
418
void wxFSWSourceHandler::OnExceptionWaiting()
419
{
420
    wxFAIL_MSG("We never receive exceptions on kqueue descriptor.");
421
}
422
423
424
// ============================================================================
425
// wxKqueueFileSystemWatcher implementation
426
// ============================================================================
427
428
wxKqueueFileSystemWatcher::wxKqueueFileSystemWatcher()
429
    : wxFileSystemWatcherBase()
430
{
431
    Init();
432
}
433
434
wxKqueueFileSystemWatcher::wxKqueueFileSystemWatcher(const wxFileName& path,
435
                                                     int events)
436
    : wxFileSystemWatcherBase()
437
{
438
    if (!Init())
439
    {
440
        wxDELETE(m_service);
441
        return;
442
    }
443
444
    Add(path, events);
445
}
446
447
wxKqueueFileSystemWatcher::~wxKqueueFileSystemWatcher()
448
{
449
}
450
451
bool wxKqueueFileSystemWatcher::Init()
452
{
453
    m_service = new wxFSWatcherImplKqueue(this);
454
    return m_service->Init();
455
}
456
457
#endif // wxHAS_KQUEUE
458
459
#endif // wxUSE_FSWATCHER
(-)b/emulators/libretro-pcsx2/files/patch-3rdparty_wxwidgets3.0_CMakeLists.txt (+14 lines)
Added Link Here
1
--- 3rdparty/wxwidgets3.0/CMakeLists.txt.orig	2020-10-29 23:31:05 UTC
2
+++ 3rdparty/wxwidgets3.0/CMakeLists.txt
3
@@ -1,10 +1,10 @@
4
 if(UNIX)
5
 set(wxUnixSources
6
+   src/unix/fswatcher_kqueue.cpp
7
    src/unix/appunix.cpp
8
    src/unix/dir.cpp
9
    src/unix/dlunix.cpp
10
    src/unix/evtloopunix.cpp
11
-   src/unix/epolldispatcher.cpp
12
    src/unix/fdiounix.cpp
13
    src/unix/stackwalk.cpp
14
    src/unix/stdpaths.cpp
(-)b/emulators/libretro-pcsx2/files/patch-3rdparty_wxwidgets3.0_UsewxWidgets.cmake (+11 lines)
Added Link Here
1
--- 3rdparty/wxwidgets3.0/UsewxWidgets.cmake.orig	2020-10-29 23:31:05 UTC
2
+++ 3rdparty/wxwidgets3.0/UsewxWidgets.cmake
3
@@ -11,7 +11,7 @@ if(UNIX)
4
    if(APPLE)
5
       add_definitions(-D__DARWIN__)
6
    else()
7
-       add_definitions(-D__LINUX__)
8
+       add_definitions(-D__BSD__)
9
    endif()
10
 elseif(WIN32)
11
    add_definitions(-D__WINDOWS__)
(-)b/emulators/libretro-pcsx2/files/patch-3rdparty_wxwidgets3.0_include_nogui_wx_setup.h (+11 lines)
Added Link Here
1
--- 3rdparty/wxwidgets3.0/include/nogui/wx/setup.h.orig	2020-10-29 23:31:05 UTC
2
+++ 3rdparty/wxwidgets3.0/include/nogui/wx/setup.h
3
@@ -1108,7 +1108,7 @@
4
 #define HAVE_SYS_SELECT_H 1
5
 
6
 /* Define if you have abi::__forced_unwind in your <cxxabi.h>. */
7
-#define HAVE_ABI_FORCEDUNWIND 1
8
+/*#define HAVE_ABI_FORCEDUNWIND 1*/
9
 
10
 /* Define if fdopen is available.  */
11
 #define HAVE_FDOPEN 1
(-)b/emulators/libretro-pcsx2/files/patch-CMakeLists.txt (+14 lines)
Added Link Here
1
--- CMakeLists.txt.orig	2020-10-29 23:31:05 UTC
2
+++ CMakeLists.txt
3
@@ -44,7 +44,10 @@ if (LIBRETRO)
4
    set(BUILD_REPLAY_LOADERS FALSE)
5
 #   add_definitions(-D__LIBRETRO__ -DDISABLE_RECORDING)
6
 #add_definitions(-D__LIBRETRO__ -DDISABLE_RECORDING -DwxUSE_UNICODE=0)
7
-add_definitions(-D__LIBRETRO__ -DDISABLE_RECORDING -DwxUSE_GUI=0)
8
+message("wxWidgets_INCLUDE_DIRS: ${wxWidgets_INCLUDE_DIRS}")
9
+include_directories(${wxWidgets_INCLUDE_DIRS})
10
+#include_directories(${gdk_INCLUDE_DIRS})
11
+add_definitions(-D__LIBRETRO__ -DDISABLE_RECORDING -DwxUSE_GUI=0 -I${gtk_INCLUDE_DIR} -D__USE_ISOC11)
12
 endif()
13
 
14
 if(NOT NO_TRANSLATION)
(-)b/emulators/libretro-pcsx2/files/patch-common_include_Utilities_General.h (+11 lines)
Added Link Here
1
--- common/include/Utilities/General.h.orig	2020-10-29 23:31:05 UTC
2
+++ common/include/Utilities/General.h
3
@@ -257,7 +257,7 @@ void MemProtectStatic(u8 (&arr)[size], const PageProte
4
 
5
 // Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it.
6
 #define SafeSysMunmap(ptr, size) \
7
-    ((void)(HostSys::Munmap((uptr)(ptr), size), (ptr) = NULL))
8
+    ((void)(HostSys::Munmap((uptr)(ptr), size), (ptr) = 0))
9
 
10
 extern void InitCPUTicks();
11
 extern u64 GetTickFrequency();
(-)b/emulators/libretro-pcsx2/files/patch-pcsx2_SPU2_spu2.cpp (+14 lines)
Added Link Here
1
--- pcsx2/SPU2/spu2.cpp.orig	2020-10-29 23:31:05 UTC
2
+++ pcsx2/SPU2/spu2.cpp
3
@@ -17,7 +17,10 @@
4
 #include "Global.h"
5
 #include "spu2.h"
6
 #include "Dma.h"
7
-#ifdef __linux__
8
+#ifdef __BSD__
9
+#include "Linux/Dialogs.h"
10
+#include "Linux/Config.h"
11
+#elif defined(__linux__)
12
 #include "Linux/Dialogs.h"
13
 #include "Linux/Config.h"
14
 #elif defined(_WIN32)
(-)b/emulators/libretro-pcsx2/pkg-descr (+9 lines)
Added Link Here
1
Standalone port of pcsx2 to libretro.
2
3
PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its
4
purpose is to emulate the PS2's hardware, using a combination of MIPS
5
CPU Interpreters, Recompilers and a Virtual Machine which manages
6
hardware states and PS2 system memory. This allows you to play PS2
7
games on your PC, with many additional features and benefits.
8
9
WWW: https://github.com/libretro/pcsx2

Return to bug 252191